Search icon
Arrow left icon
All Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Newsletters
Free Learning
Arrow right icon
Learning Python Application Development

You're reading from  Learning Python Application Development

Product type Book
Published in Sep 2016
Publisher Packt
ISBN-13 9781785889196
Pages 454 pages
Edition 1st Edition
Languages
Author (1):
Ninad Sathaye Ninad Sathaye
Profile icon Ninad Sathaye

Table of Contents (18) Chapters

Learning Python Application Development
Credits
Disclaimers
About the Author
About the Reviewer
www.PacktPub.com
Preface
1. Developing Simple Applications 2. Dealing with Exceptions 3. Modularize, Package, Deploy! 4. Documentation and Best Practices 5. Unit Testing and Refactoring 6. Design Patterns 7. Performance – Identifying Bottlenecks 8. Improving Performance – Part One 9. Improving Performance – Part Two, NumPy and Parallelization 10. Simple GUI Applications Index

Chapter 7. Performance – Identifying Bottlenecks

So far, you have learned various ways to make the application robust and accommodating for new features. Now, let's discuss techniques to improve the application performance. This broad topic is split into a series of three chapters—this is the first one in this series. It will cover the following topics:

  • Basic ways to clock the application runtime

  • How to identify the runtime performance bottlenecks by profiling the code

  • Basic memory profiling with the memory_profiler package

  • Big O notation for the computational complexity

To understand these concepts better, we will develop an interesting game scenario called Gold Hunt. You will soon realize that the application runs very slow when you increase the input data size. This chapter will elaborate on techniques to pinpoint such problems.

Overview of three performance chapters


Before we dive into the main discussion, let's first understand how the chapters on performance improvement are organized. As mentioned earlier, this discussion is split into a series of three interlinked chapters.

More focus on the runtime performance

The term performance improvement can mean several things. One can be talking about improving the runtime (CPU usage), making the application memory efficient, reducing the network consumption, or a combination of these. In this book, we will primarily focus on the runtime performance improvement. We will also discuss the memory consumption aspect, but the discussion will be limited to the memory profiling technique and the use of generator expressions.

The first performance chapter

You are reading the first chapter in this series. It does some preparatory work to improve the application performance. This preparation involves measuring the runtime, identifying pieces of the code that cause the performance...

Scenario – The Gold Hunt


You recently introduced a new scenario in the game—to meet the expenses of his army, Sir Foo is out on a mission to collect gold from a recently acquired territory. The scenario starts with Sir Foo arriving at a place full of gold coins, jewelry, and so on. There are a couple of problems though. Firstly, the gold is scattered all over the field. Secondly, Sir Foo doesn't have time to collect all the gold on the field.

What you see behind Sir Foo is an imaginary gold field. Sir Foo will enter from the left side and travel across the field. He will only collect the coins lying along his path and ignore all the remaining gold scattered across the field.

Let's represent this gold field as a circle with a radius of nearly 10 miles (diameter of 20 miles), and center located at coordinates x = 0 and y = 0, as shown in the following screenshot:

Observe the following screenshot. The dotted line (the diameter of the field) shows the path that Sir Foo traverses on his...

The problem


In the game scenario, you allowed the users to tweak certain parameters. For example, the users can control the total number of coins on the field or modify the radius of the search circle. Unknowingly, you opened a new can of worms. For a large input size, the program runs very slow. For example, one variant of the game, The Great Dwarf of the Foo mountain, is performing the gold hunt. Let's hear what he has to say:

If you change field_coins from 5000 to 1000000 and set search_radius to 0.1, the application will take quite a bit of time to finish. Here is the updated main execution code with these new parameters:

if __name__ == '__main__': 
    game = GoldHunt(field_coins=1000000, search_radius=0.1) 
    game.play() 

If you increase the coins further or make the search radius even smaller, it will severely affect the application runtime.

Tip

Warning!

If you run the following code, depending on your machine configuration, it can slow down your machine, take longer time to finish...

Identifying the bottlenecks


In the previous section, we saw how a different choice of input parameters degrades the application runtime. Now, we need some way to accurately measure the execution time and find out the performance bottlenecks or the time consuming blocks of the code.

Measuring the execution time

Let's start by monitoring the time taken by the application. To do this, we will use Python's built-in time module. The time.perf_counter function is a performance counter that returns a clock with the highest available resolution. This function can be used to determine the time interval or the system-wide time difference between the two consecutive calls to the function.

Tip

The time.perf_counter function is available in Python versions 3.3 onwards. If you have an older version of Python (for example, version 2.7), use time.clock() instead. On Unix, time.clock() returns a floating point number within seconds that represents the processor time. On Windows, it returns the elapsed wall-clock...

Memory profiling


The profiling techniques we have covered so far aim at finding the runtime bottlenecks. Let's briefly discuss memory profiling, another important aspect of profiling.

The memory_profiler package

For memory profiling, we will use a popular Python package called memory_profiler. It can be installed using pip. Here is how to install it on Linux from the command line:

$ pip install memory_profiler

The documentation highly recommends installing the psutils module. It also suggests that, in order for memory_profiler to work on Windows OS, you will need the psutil module. The psutil module can be installed using pip, as follows:

$ pip install psutil 

Tip

For more information on memory_profiler, check out the following page: https://pypi.python.org/pypi/memory_profiler.

Just like line_profiler, the memory_profiler package uses the @profile decorator above the function name. Let's add the decorator @profile just above the generate_random_points function, and then run the memory profiler...

Algorithm efficiency and complexity


An algorithm is a set of instructions to solve a particular problem. In this context, an algorithm can be a function or even a simple operation that adds two numbers. Let's understand two related terms: algorithm efficiency and algorithm complexity.

Algorithm efficiency

Algorithm efficiency indicates the computation resources consumed by an algorithm. Typically, the lower the resource consumption, the better the efficiency. The computational resources can mean several things. One can be talking about the runtime (CPU usage), the memory consumption (RAM or hard disk) or the network consumption, or a combination of these.

The application requirement determines which resource takes precedence over the others. For example, in a web application, the network usage can be more important than the disk space. For a scientific application, you might have all the memory you need but the runtime can be a pain in the neck, and so on. In this book, we will limit our discussion...

Big O notation


In simple terms, the big O or big Oh notation is a way to represent the computational complexity of an algorithm. Here, the O is the letter O, as in order, and not the number zero. The big O indicates an upper bound or the worst-case scenario of the complexity of an algorithm (details to follow in the next section). This concept can be better explained with an example. Let's take a look at the following code:

num = 100 
x = []
for i in range(num): 
    x.append(i)

Let's call this trivial code fragment an algorithm. It is a simple operation that appends a number to the list inside a for loop. Here, num represents the size of the input used by the algorithm. If you increase num, the algorithm will have to do more work inside the for loop. Increase it further, and the poor algorithm will have to do even more work. Thus, the time taken by the algorithm depends on the value of num and can be expressed as a growth function, f(n). Here, n represents the size of the input that corresponds...

Summary


This chapter was the first one in the series of three chapters based on performance. It laid the ground work to improve application performance. We learned how to record the runtime using the time module. We also saw how the timeit module can be used to measure the performance of small pieces of code. We took a practical problem where an application ran fine when working with a small input, but, as the input grew larger, it slowed down considerably. With this example, we learned how to identify the bottlenecks using cProfile and display the results using pstats.

We saw how the line_profiler module can help locate the time consuming statements inside a function. While most of the discussion was focused on the runtime performance, we briefly covered the memory_profiler module. This module enabled line-by-line analysis of memory consumption for the given functions. Finally, we learned about the big O notation that represents the computational complexity of an algorithm.

Now that we have...

lock icon The rest of the chapter is locked
You have been reading a chapter from
Learning Python Application Development
Published in: Sep 2016 Publisher: Packt ISBN-13: 9781785889196
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $15.99/month. Cancel anytime}