Skip to the content
Documentation
Help Start
Reading in:
  • German: 9,059 of 9,059 pages
About the help in other languages
All help pages

Profiling PHP code

Measuring and speeding up PHP code in Exponential - exp:benchmark for pages, kernel probes and micro benchmarks, eZDebug accumulators around your own code, the debug bar's SQL and memory figures, the OPcache profile…

Download as PDF

Address: https://doc.exponential.earth/learninminutes/exphelp/viewer/help/php-developers/profiling-php-code.md

On this page

Profiling PHP code

This page is for PHP developers who make code faster, or who must prove a change did not make it slower. The method is always the same: measure, change one thing, measure again, under the same conditions. The application view is Profiling and performance; the full guide is Benchmarking Exponential.

Contents

  1. Three levels of measurement
  2. Pages: exp:benchmark
  3. The kernel and micro benchmarks
  4. Inside one request
  5. OPcache, under any engine
  6. The SQL query cache
  7. Causes that recur
  8. Measuring fairly

Three levels of measurement

LevelToolAnswers
whole pages over HTTPexp:benchmarkis the site faster or slower, and by how much
kernel operations in-processexp:benchmark kernelwhich part of a request costs (boot, render, INI, fetch, database, cache)
your code in one requestaccumulators, the debug barwhere in your code the time goes

Pages: exp:benchmark

php bin/php/console exp:benchmark --save=var/benchmark/base.json
# change something
php bin/php/console exp:benchmark --baseline=var/benchmark/base.json --threshold=15
php bin/php/console exp:benchmark --cold --requests=50                 # past the response caches
php bin/php/console exp:benchmark --compare=https://www.example.com,https://www.example.com:8080

It requests a set of pages many times after a warm-up and prints median, p90, p99 and more. --baseline with --threshold turns it into a regression check that fails when a page got slower by more than the threshold (Benchmark).

The kernel and micro benchmarks

php bin/php/console exp:benchmark kernel --repeat=30 --save=var/benchmark/kernel.json
php bin/php/benchmark.php micro --baseline=tests/benchmark/baseline.json --all-checks

The kernel probes time boot, render (cold and warm), INI load, a content fetch, a database round trip and cache writes and reads in-process. The micro benchmark times pure PHP hot paths without HTTP or a database; CI's Performance workflow runs it against tests/benchmark/baseline.json on PHP 8.5 with OPcache off, as a warning.

Inside one request

Wrap the code you suspect in an accumulator:

eZDebug::accumulatorStart( 'acmereport_totals', 'acmereport_total', 'Monthly totals' );
$totals = acmeReportService::monthlyTotals( $month );
eZDebug::accumulatorStop( 'acmereport_totals' );

With debug output on, the bar shows:

  • Timing: your accumulators with their total time and call count, next to the kernel's;
  • SQL: the number of statements, their time and share of the page, slowest first (SQLOutput=enabled);
  • Memory: peak and the steps that took the most;
  • Templates: how many templates were used.

The summary turns figures yellow or red against debugbar.ini thresholds, which makes a new hot spot visible at a glance (The debug bar for PHP developers).

OPcache, under any engine

The kernel can write one line per request saying how the request used OPcache: hits and misses, the scripts served most, and included files that OPcache does not hold (each of those is compiled again whenever it is included). It is off unless the file var/tmp/opcache_profile.on exists; the lines go to var/tmp/opcache_profile.log (ezpKernelWeb::writeOPcacheProfile()). Use it to compare engines; remove the switch file afterwards (Velocity and the opcode cache).

The SQL query cache

settings/querycache.ini (Mode=off by default) caches the results of repeated read queries (in APCu where the process has it, else in files, by default). Measure with it on and off: a page that issues the same query many times gains, a page with unique queries does not. It does not apply to MongoDB (SQL query cache).

Causes that recur

SymptomUsual causeFix
many queries per pagefetches in loops, dataMap() on every item of a listfetch once; limit; a cache block
a list gets slower with the datano limit, or a count of everythingpage it; bounded counts
memory grows in a commandobjects kept in the kernel's in-memory cacheseZContentObject::clearCache() between pages
a slow publishheavy work in a workflow event or listenera queue or a content job
slow after deploycaches clearedwarm them (OPcache and cache preloading)
slow only under Velocity after a changeworkers not restarted, or OPcache not revalidatingexp:velocity deploy

Measuring fairly

  • Same machine, nothing else running, OPcache as in production, Xdebug off.
  • Compare two servers by alternating requests, not by timing one after the other.
  • Record the environment with each run; a comparison with a baseline from another setup says little.
  • Keep the runs: commit a baseline file for your extension and compare against it before a release.

Become an Exponential Partner

Partners share their information, provide funding, contribute back and develop the products with us, and that is how Exponential grows. A partner website and dashboard are planned for mid-2027: please become a partner today to speed up our growth rate and land new features faster.

Something wrong on this page? Report an error

Documentation license

This documentation is free documentation, licensed under the GNU Free Documentation License 1.3 or later.

Exponential Copyright © 1998-2026 Exponential Foundation and 7x