Stay in Control: Manual Code Instrumentation

By Fabien Potencier, on Apr 10, 2015

A couple of weeks ago, I wrote about Blackfire usage simplicity thanks to auto-instrumentation. When a PHP script is executed, the Probe (Blackfire’s PHP C extension) detects if it needs to instrument the code thanks to a signed HTTP header for web requests or a signed environment variable for CLI applications. The signed header or env variable is automatically and transparently created by the browser extension or by the Blackfire CLI tool and tied to your personal credentials.

Auto-instrumentation allows to profile applications without any code changes, but another nice benefit is that the execution of a non-signed PHP script does not have any performance overhead; that’s why it is safe to enable Blackfire on production servers as instrumentation can only be triggered by an authorized client.

Auto-instrumentation works for the vast majority of profiling needs but manual instrumentation is sometimes useful, like when you want to profile a small part of a long-running script.

For instance, consider a worker process; one could decide to launch the profiling on each processed message and discard everything else. This way, you will get a profile averaged by message instead of one big profile. Or you can do the opposite and try to find bottlenecks happening between messages processing.

As of version 0.21 of the C probe, you can manually instrument your code. Let’s start with a simple “Hello World!” application:

// hello.php

function printHello()
{
    echo "Hello World!";
}

// get the probe main instance
$probe = BlackfireProbe::getMainInstance();

// won't show up in the profile
printHello();

// start the profiling
$probe->enable();

printHello();

// stop the profiling
// send the result to Blackfire
$probe->close();

// won't show up in the profile
printHello();

If you run this script via php hello.php, profiling will be disabled as the probe won’t detect the signed env variable. To enable the profiling, you must run the script via the Blackfire CLI tool:

blackfire run --slot 1 php hello.php

As expected, the profile shows only one call to the printHello() function (the two other ones are not part of the profile).

hello-one-call

But there is more. You can decide to profile several parts of the execution and exclude some other ones; that’s possible by calling disable() instead of close():

function printHello()
{
    echo "Hello World!";
}

$probe = BlackfireProbe::getMainInstance();

$probe->enable();

printHello();

// stop the profiling temporarily
// flush the collected profile to the output (sent to the agent)
$probe->disable();

// won't show up in the profile
printHello();

// re-enable the instrumentation
// aggregate data in the same profile
$probe->enable();

printHello();

// stop the profiling
// send the result to Blackfire
$probe->close();

If you run the above script, you will still see two calls to printHello(), the first one and the last one.

Last, but not the least, you can also decide to discard profiling data even after the instrumentation has been enabled by using discard():

function printHello()
{
    echo "Hello World!";
}

$probe = BlackfireProbe::getMainInstance();

$probe->enable();

printHello();

// discard the profiling data
$probe->discard();

// re-enable the instrumentation
$probe->enable();
printHello();
$probe->close();

Here, you will only see one call as the first one has been instrumented but discarded.

Note that you can also do manual instrumentation for Web scripts; use the blackfire curlcommand or the Chrome extension.

blackfire curl --slot 1 http://symfony.com/

There is one more thing I wanted to mention: as for auto-instrumentation, when you do not explicitly ask for a profile, the manual instrumentation code does nothing; it allows you to deploy instrumented code without any performance overhead (but you need Blackfire installed on your servers of course).

Manual-instrumentation opens up a lot of new opportunities for Blackfire and we would love to hear about your own usage on Twitter via our official hashtag: #blackfireio.

Happy manual profiling!

Fabien Potencier

Fabien Potencier is the CEO and founder of Blackfire.io. He founded the Symfony project in 2004 as he constantly looked for better ways to build websites. Fabien is also the creator of several other Open-Source projects, a writer, a blogger, a speaker at international conferences, and the happy father of two wonderful kids.