Profile Python Functions Using a Decorator

By Jérôme Vieilledent, on Nov 02, 2020

The Blackfire Python SDK provides various ways to profile your code, including automatic instrumentation on supported frameworks, or by using the probe.run() Context Manager.

Manual vs Automatic instrumentation

There are several ways to triggers profiles for your application, and it is important to distinguish whether to opt in for manual or automatic instrumentation.

Automatic Instrumentation

Automatic instrumentation means that the Blackfire Probe is automatically initialized when the X-Blackfire-Query HTTP header is detected, or when the X_BLACKFIRE_QUERY environment variable is present in the CLI context. The generated profile takes every function calls into account.

In the HTTP context, the auto-instrumentation is enabled when you trigger a profile from the browser extension, or with the blackfire curl command. At the moment, it is only available for specific frameworks when using the blackfire-python command (read more in the dedicated article about blackfire-python).

In the CLI context, the auto-instrumentation is enabled when running your Python script using the blackfire-python run command:

blackfire-python run python my_script.py

The “on-demand profiling” characteristic of the auto-instrumentation makes it production safe, as it won’t impact any user other than yourself in terms of overhead.

Manual Instrumentation

The manual instrumentation implies that you control what the Blackfire Probe is instrumenting. You can do this using the Python SDK, by initializing a probe yourself.

While using manual instrumentation gives you more control, it also means that you need to be careful before shipping your app into production, as you may initialize a probe (and thus generate a profile) for each request! This would mean adding an overhead for every request.

Introducing the @profile Decorator

The latest version of the Blackfire Probe for Python introduces some syntactic sugar, taking advantage of Python Decorators and simplifying the developer experience: the @profile decorator.

This decorator allows you to instrument the code of a function in a very minimalistic way:

from blackfire import profile

@profile
def foo():
    import time
    time.sleep(1.0)

foo()

In this example, the foo() function is instrumented each time it is called. The probe initializes and creates a dedicated profile.

Be careful not to push such decorated code into production as this constitutes a manual instrumentation. As such, a probe is initialized each time the decorator is called.

Give Blackfire a try?

Play with the demo or subscribe now!

Happy Profiling!

Jérôme Vieilledent

As a Developer Advocate, Jérôme is all about spreading the love! His technical/development background enable him to talk as a peer to peers with our developer users. You’ll read his tips and advices on performance management with Blackfire. And he’ll support you as a day-to-day user.