Profiling with cProfile

The Python library provides us with an application profiler which can help ease the life of the developers by allowing to easily profile not only the whole application, but also the individual components of the application.

Profile is a built-in code profiler that comes bundled as a module with some of the python distributions. The module is able to collect the information about the individual method calls that have been made, along with the profiling of any of the calls made to third-party functions.

Once these details are collected, the module provides us with a host of statistics that can help us get a better picture of what's going on inside the component. Before we dive into what details are collected and represented, let's see how we can use cProfile in our application.

The following code snippet shows us a sample of how to use cProfile in our code:

import cProfile
import hashlib
def encrypt_password(password, salt):
"""Encrypt the provided password.

Keyword arguments:
password – The password to be encrypted
salt – The salt to be used for padding the password

Returns:
String
"""
profiler = cProfile.Profile()
profiler.enable()
passwd_hash = hashlib.pbkdf2_hmac('sha256', password.encode('utf-8'), salt, 10000).hex()
profiler.disable()
profiler.print_stats()
return passwd_hash

In the preceding code, we enabled the profiling using cProfile. Getting cProfile to work for us is a straightforward process. We first import the module as usual through the use of import statements. Once the module has been imported, we need to create a new cProfile Profile instance. This is done by calling the Profile() constructor of the cProfile module:

profiler = cProfile.Profile()

Once the profiler instance is created, we start the profiler by calling the enable() method on the profiler. After this, whatever operations we do will be profiled by our profiler. Once we are done executing, we call the disable() method on the profiler to stop the collection of the metrics.

Now, to get the collected statistics, we make a call to the print_stats() method of the profiler instance that was created.

Let's take a look at what statistics were generated based on when we ran the preceding piece of code:

         3 function calls in 0.015 seconds

Ordered by: standard name

ncalls tottime percall cumtime percall filename:lineno(function)
1 0.015 0.015 0.015 0.015 {built-in method _hashlib.pbkdf2_hmac}
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
1 0.000 0.000 0.000 0.000 {method 'encode' of 'str' objects}

As we can see from the preceding output, we got some detailed statistics about what our method did. These statistics consist of a number of details, such as the function that was called, how many calls were made to the function (ncalls), the total time spent in a function (tottime), and how much time an individual call took (percall).

These are some really important statistics from a production-grade-application point of view because these statistics not only provide the information about a particular slow operation, but also about how many times that operation was called so that it can be determined why something is performing slower than expected.

Now, we know of a built-in profiler that can help us profile the calls with much more timing detail than we were doing previously, and this can help us in understanding the slowdowns. What if the performance issue was not a slowdown but an anomaly related to the increased memory usage of the application while doing a certain job? Our cProfile profiler doesn't provides us with those details, and we need to know about them to properly address the issue.

For this, we get out of our comfort zone of utilizing the Python standard library, and move into the third-party libraries that are available to us through the use of the python package manager.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.221.66.185