Profiling Laravel with Blackfire and Xdebug | Mohamed Said        [  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MH.png)   Mohamed Said Laravel Backend Engineer  ](https://www.msaied.com) [ Home ](https://www.msaied.com) [ Projects ](https://www.msaied.com/projects) [ Articles  ](https://www.msaied.com/articles) [ Certificates ](https://www.msaied.com/certificates) [ Contact ](https://www.msaied.com#contact-section) 

       [  ](https://github.com/EG-Mohamed)       

 [ Home ](https://www.msaied.com) [ Projects ](https://www.msaied.com/projects) [ Articles ](https://www.msaied.com/articles) [ Certificates ](https://www.msaied.com/certificates) [ Contact ](https://www.msaied.com#contact-section) 

  [ home ](https://www.msaied.com)    [ articles ](https://www.msaied.com/articles)    Blackfire &amp; Xdebug Profiling in Laravel: Finding Real Bottlenecks        On this page       1. [  Why Guessing Is Expensive ](#why-guessing-is-expensive)
2. [  Xdebug: Callgrind Profiles Locally ](#xdebug-callgrind-profiles-locally)
3. [  Reading the Call Graph ](#reading-the-call-graph)
4. [  Blackfire: Continuous Performance Assertions ](#blackfire-continuous-performance-assertions)
5. [  Profiling a Specific Artisan Command ](#profiling-a-specific-artisan-command)
6. [  Instrumenting Custom Code ](#instrumenting-custom-code)
7. [  Combining Both Tools Effectively ](#combining-both-tools-effectively)
8. [  Takeaways ](#takeaways)

  ![Blackfire & Xdebug Profiling in Laravel: Finding Real Bottlenecks](https://cdn.msaied.com/608/26a2b1fe183034ea35445954544f68f1.png)

  #laravel   #performance   #profiling   #blackfire   #xdebug  

 Blackfire &amp; Xdebug Profiling in Laravel: Finding Real Bottlenecks 
=======================================================================

     30 Aug 2026      3 min read    ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MJ.jpg)  Mohamed Said  

       Table of contents

1. [  01   Why Guessing Is Expensive  ](#why-guessing-is-expensive)
2. [  02   Xdebug: Callgrind Profiles Locally  ](#xdebug-callgrind-profiles-locally)
3. [  03   Reading the Call Graph  ](#reading-the-call-graph)
4. [  04   Blackfire: Continuous Performance Assertions  ](#blackfire-continuous-performance-assertions)
5. [  05   Profiling a Specific Artisan Command  ](#profiling-a-specific-artisan-command)
6. [  06   Instrumenting Custom Code  ](#instrumenting-custom-code)
7. [  07   Combining Both Tools Effectively  ](#combining-both-tools-effectively)
8. [  08   Takeaways  ](#takeaways)

 Why Guessing Is Expensive
-------------------------

Most performance work starts with a hunch: "It must be the N+1 query" or "The cache is probably cold." Hunches waste hours. Profilers give you a call graph with wall-clock time, CPU time, memory delta, and I/O — so you fix the right thing first.

This article covers two complementary tools:

- **Xdebug** — free, always available, great for local deep-dives with a GUI like PHPStorm or KCachegrind.
- **Blackfire** — commercial, CI-friendly, built for continuous performance testing with assertions.

---

Xdebug: Callgrind Profiles Locally
----------------------------------

Install Xdebug 3 and add to `php.ini`:

```ini
[xdebug]
xdebug.mode=profile
xdebug.output_dir=/tmp/xdebug
xdebug.profiler_output_name=cachegrind.out.%p.%r

```

Trigger a profile for a single request by appending `?XDEBUG_PROFILE=1` or setting the cookie. For a CLI job:

```bash
XDEBUG_MODE=profile php artisan queue:work --once

```

Open the resulting `cachegrind.out.*` file in **KCachegrind** (Linux) or **QCachegrind** (macOS). Sort by *Self Cost* to find functions that consume time without delegating — these are your actual hot paths, not just callers.

### Reading the Call Graph

A common surprise: `PDOStatement::execute` shows up with 40 % self cost because a Blade partial triggers 60 lazy-loaded relations. The call graph makes the chain obvious:

```php
View::render
  └─ BlogPost::author()      ← repeated 50×
       └─ PDOStatement::execute

```

Fix it with `with('author')` on the controller query, re-profile, confirm the cost drops.

---

Blackfire: Continuous Performance Assertions
--------------------------------------------

Blackfire's killer feature is not the flame graph — it's **assertions in CI**. You write a `.blackfire.yaml` at the project root:

```yaml
tests:
  "Homepage loads fast":
    path: /
    assertions:
      - "main.wall_time < 200ms"
      - "metrics.sql.queries.count < 10"
      - "metrics.http.requests.count == 1"

```

Push to a branch, run `blackfire run php artisan blackfire:test` (or the GitHub Action), and the build fails if a regression sneaks in. This is performance-as-code.

### Profiling a Specific Artisan Command

```bash
blackfire run php artisan import:products --limit=100

```

Blackfire uploads the trace to its dashboard. Filter by **exclusive time** to find the single most expensive function call. A real example: `json_decode` inside a loop consuming 18 % of wall time because a 2 MB payload was decoded once per row instead of once per batch.

### Instrumenting Custom Code

For long jobs, add manual probes so Blackfire can segment the timeline:

```php
use Blackfire\Client;
use Blackfire\Profile\Configuration;

$blackfire = new Client();
$probe = $blackfire->createProbe((new Configuration())->setTitle('Batch import'));

foreach ($chunks as $chunk) {
    $this->processChunk($chunk);
}

$blackfire->endProbe($probe);

```

This gives you a named segment in the timeline rather than one undifferentiated blob.

---

Combining Both Tools Effectively
--------------------------------

| Scenario | Tool | |---|---| | Local deep-dive, no account needed | Xdebug + KCachegrind | | CI regression gate | Blackfire assertions | | Profiling a queue job in staging | Blackfire `run` | | Memory leak hunt | Xdebug memory snapshots | | Comparing two implementations | Blackfire comparison view |

A practical workflow: use Xdebug locally to understand *what* is slow, fix it, then write a Blackfire assertion so it never regresses.

---

Takeaways
---------

- **Never optimise without a profiler** — wall-clock logs lie about where time is actually spent.
- Xdebug callgrind + KCachegrind is zero-cost and reveals the full PHP call graph.
- Blackfire assertions in CI make performance a first-class build constraint.
- Sort by *exclusive/self* time, not inclusive, to find the real culprit.
- Instrument long-running jobs with Blackfire probes to segment the timeline.
- Fix one bottleneck at a time and re-profile; compound fixes mask each other's impact.

 Found this useful?

          [  ](https://twitter.com/intent/tweet?url=https%3A%2F%2Fwww.msaied.com%2Farticles%2Fblackfire-xdebug-profiling-in-laravel-finding-real-bottlenecks-2&text=Blackfire+%26+Xdebug+Profiling+in+Laravel%3A+Finding+Real+Bottlenecks) [  ](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fwww.msaied.com%2Farticles%2Fblackfire-xdebug-profiling-in-laravel-finding-real-bottlenecks-2) 

 Frequently Asked Questions 
----------------------------

  3 questions  

     Q01  Can I use Xdebug profiling in production?        Avoid it. Xdebug profiling adds significant overhead (often 2–5×) and writes large files to disk. Use it locally or in a dedicated staging environment. For production profiling, Blackfire's agent has much lower overhead and is designed for live traffic sampling. 

      Q02  How do Blackfire assertions differ from just checking response time in a test?        Blackfire assertions inspect the internal call graph — SQL query count, HTTP sub-requests, memory allocations, and specific function call counts — not just the final response time. This means you can catch a regression like an extra 20 queries even if the total wall time stays under your threshold due to a fast database in CI. 

      Q03  Does Xdebug profiling work with Laravel Octane?        Partially. Because Octane reuses worker processes, Xdebug's per-request profiler output can mix traces across requests. The safest approach is to profile with Octane disabled locally, or use Blackfire which has explicit Octane support via its agent. 

  Continue reading

 More Articles 
---------------

 [ View all    ](https://www.msaied.com/articles) 

 [ ![Recursive CTEs and Hierarchical Data in Laravel with PostgreSQL](https://cdn.msaied.com/607/ac508dd27011f0f2c57b0bee7707b740.png) laravel postgresql eloquent 

### Recursive CTEs and Hierarchical Data in Laravel with PostgreSQL

Learn how to query trees and hierarchies—categories, org charts, threaded comments—using recursive CTEs in Pos...

  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MJ.jpg)  Mohamed Said 

 29 Aug 2026     3 min read  

  Read    

 ](https://www.msaied.com/articles/recursive-ctes-and-hierarchical-data-in-laravel-with-postgresql) [ ![Laravel API Resources: Sparse Fieldsets, Cursor Pagination, and Per-Route Rate Limiting](https://cdn.msaied.com/606/93349b03f4527b9100157c6774bb4ce2.png) laravel api eloquent 

### Laravel API Resources: Sparse Fieldsets, Cursor Pagination, and Per-Route Rate Limiting

Go beyond basic JsonResource usage. This guide covers sparse fieldsets, cursor-based pagination for large data...

  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MJ.jpg)  Mohamed Said 

 29 Aug 2026     4 min read  

  Read    

 ](https://www.msaied.com/articles/laravel-api-resources-sparse-fieldsets-cursor-pagination-and-per-route-rate-limiting) [ ![Laravel Starter Kits Now Ship with Vite+](https://cdn.msaied.com/604/ff70a112664fcb8b68719ab94a842145.png) Laravel Vite+ Starter Kits 

### Laravel Starter Kits Now Ship with Vite+

All Laravel starter kits now use Vite+, the unified toolchain that replaces ESLint and Prettier with Oxlint an...

  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MJ.jpg)  Mohamed Said 

 28 Aug 2026     3 min read  

  Read    

 ](https://www.msaied.com/articles/laravel-starter-kits-now-ship-with-vite) 

   [  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MH.png)   Mohamed Said Laravel Backend Engineer  ](https://www.msaied.com)Senior Backend Engineer specializing in Laravel, scalable SaaS platforms, APIs, and cloud infrastructure. I build secure, high-performance web applications that help businesses grow.

Explore

- [Home](https://www.msaied.com)
- [Projects](https://www.msaied.com/projects)
- [Articles](https://www.msaied.com/articles)
- [Certificates](https://www.msaied.com/certificates)
- [Contact](https://www.msaied.com#contact-section)

Connect

- [   hello@msaied.com ](mailto:hello@msaied.com)
- [   +20 109 461 9204 ](tel:+201094619204)

© 2026 Mohamed Said. All rights reserved.

 [  ](https://github.com/EG-Mohamed) [  ](https://www.linkedin.com/in/msaiedm/) [  ](https://wa.me/201094619204) [  ](mailto:hello@msaied.com) [  ](https://drive.google.com/file/u/0/d/1MF20IPRJyzfy32mhEutjL5EpSls0w2Q8/view)
