Comparisons: Validate Performance Changes, Find Side Effects

Video not working?

It looks like your browser may not support the H264 codec. If you're using Linux, try a different browser or try installing the gstreamer0.10-ffmpeg gstreamer0.10-plugins-good packages.

Thanks! This saves us from needing to use Flash or encode videos in multiple formats. And that let's us get back to making more videos :). But as always, please feel free to message us.

We've just updated our code to make a COUNT query instead of querying for all the comments for a user... just to count them. So, the page will definitely be faster. Right? Are you absolutely sure? Well, I think it will be faster... but sometimes making one part of your code faster... will make other parts slower. Fortunately, Blackfire has a special way to prove that a performance tweak does in fact help.

Let's profile the page now - I'll refresh... then click to profile. Give it a name to stay organized [Recording] Show page after count query.

Ok! Let's go see the call graph! https://bit.ly/sfcast-bf-profile2

Hey! 270 milliseconds total time - the last one was 415. So it is faster. We win! Tutorial over!

Well... yeah, I agree: it does look faster. But an important aspect of optimization is understanding why something is faster. Like, did this reduce CPU time? I/O wait time? And, maybe more importantly, did this change cause anything to be worse? For example, a change might decrease CPU time, but increase memory. If that happened, would the change really be a good one? It depends.

Comparing Profiles

This leads me to one of my favorite tools from Blackfire: the ability to compare profiles. Click back to your dashboard: the top two profiles are from the initial profile and then the page after using the COUNT query. On the right, hover over the "Compare" button on the original, click, then click the new one.

Say hello to the comparison view: https://bit.ly/sf-bf-compare1-2. Everything that's faster, or "better" is in blue. Anything that's slower or worse will be in red. And yea, it looks like the new profile is better in every single category. Ok, the I/O wait is higher - but .1 millisecond higher - that's just "noise".

Anyways, the comparison proves that this was a good change. Really, it's a huge win! On the call graph, in the darkest blue, the critical path this time is the path that improved the most. Click the UnitOfWork call now. Wow. The inclusive time is down by 90 milliseconds and even the memory plummeted: down 1.39 megabytes.

Tip

The SQL Query information requires a Profiler plan or higher.

But wait. One of the items on top is called "SQL Queries". The total query time is less than before... but we've added 5 more queries. We removed these 18 queries... but added 23 new ones.

Is that a problem? Probably not. Overall, this change was good. And if having too many queries does create a real problem - not just an imaginary one of "too many queries" - Blackfire will help us discover that. The big takeaway here is: don't just assume that a performance enhancement... is actually better. We'll see this later - not every change we'll do in this tutorial will prove to be a good one.

Next: Blackfire has a deep understanding of PHP, database queries, Redis calls and even libraries like Symfony, Doctrine, Magento, Composer, eZ platform, Wordpress and others. Thanks to that, it automatically detects problems and recommends solutions.

Leave a comment!

This tutorial can be used to learn how to profile any app - including Symfony 5.

What PHP libraries does this tutorial use?

// composer.json
{
    "require": {
        "php": "^7.1.3",
        "ext-ctype": "*",
        "ext-iconv": "*",
        "blackfire/php-sdk": "^1.20", // v1.20.0
        "sensio/framework-extra-bundle": "^5.4", // v5.5.1
        "symfony/console": "4.3.*", // v4.3.10
        "symfony/dotenv": "4.3.*", // v4.3.10
        "symfony/flex": "^1.3.1", // v1.6.0
        "symfony/form": "4.3.*", // v4.3.10
        "symfony/framework-bundle": "4.3.*", // v4.3.9
        "symfony/http-client": "4.3.*", // v4.3.10
        "symfony/orm-pack": "^1.0", // v1.0.7
        "symfony/security-bundle": "4.3.*", // v4.3.10
        "symfony/serializer-pack": "^1.0", // v1.0.2
        "symfony/twig-bundle": "4.3.*", // v4.3.10
        "symfony/validator": "4.3.*", // v4.3.10
        "symfony/webpack-encore-bundle": "^1.6", // v1.7.2
        "symfony/yaml": "4.3.*", // v4.3.10
        "twig/extensions": "^1.5" // v1.5.4
    },
    "require-dev": {
        "doctrine/doctrine-fixtures-bundle": "^3.2", // 3.2.2
        "fzaninotto/faker": "^1.8", // v1.8.0
        "symfony/debug-pack": "^1.0", // v1.0.7
        "symfony/maker-bundle": "^1.13", // v1.14.3
        "symfony/test-pack": "^1.0" // v1.0.6
    }
}