PHPackages                             noisebynorthwest/php-spx - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Debugging &amp; Profiling](/categories/debugging)
4. /
5. noisebynorthwest/php-spx

ActivePhp-ext[Debugging &amp; Profiling](/categories/debugging)

noisebynorthwest/php-spx
========================

A simple &amp; straight-to-the-point PHP profiling extension with its built-in web UI

v0.4.22(7mo ago)2.6k594↓33.3%99[59 issues](https://github.com/NoiseByNorthwest/php-spx/issues)[4 PRs](https://github.com/NoiseByNorthwest/php-spx/pulls)GPL-3.0-or-laterCPHP &gt;=5.4.0 &lt;8.6.0CI passing

Since Jun 25Pushed 5mo ago35 watchersCompare

[ Source](https://github.com/NoiseByNorthwest/php-spx)[ Packagist](https://packagist.org/packages/noisebynorthwest/php-spx)[ Docs](https://github.com/NoiseByNorthwest/php-spx)[ RSS](/packages/noisebynorthwest-php-spx/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (10)DependenciesVersions (8)Used By (0)

SPX - A simple profiler for PHP
===============================

[](#spx---a-simple-profiler-for-php)

[![Build Status](https://github.com/NoiseByNorthwest/php-spx/actions/workflows/main.yml/badge.svg)](https://github.com/NoiseByNorthwest/php-spx/actions/workflows/main.yml)[![Supported PHP versions: 5.4 .. 8.x](https://camo.githubusercontent.com/fbd3dcf27d95f7ed403b3ac285354827fe2a1ec133a38e20a790aca0f2ce0356/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f7068702d352e342d2d382e352d626c75652e737667)](https://camo.githubusercontent.com/fbd3dcf27d95f7ed403b3ac285354827fe2a1ec133a38e20a790aca0f2ce0356/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f7068702d352e342d2d382e352d626c75652e737667)[![Supported platforms: GNU/Linux, macOS & FreeBSD](https://camo.githubusercontent.com/a7d1a79410a6338af131215df9da517bf4b39bea619c92ba6f0fd794be074a8d/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f706c6174666f726d2d474e552f4c696e75782532302537432532306d61634f53253230253743253230467265654253442532302d79656c6c6f77)](https://camo.githubusercontent.com/a7d1a79410a6338af131215df9da517bf4b39bea619c92ba6f0fd794be074a8d/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f706c6174666f726d2d474e552f4c696e75782532302537432532306d61634f53253230253743253230467265654253442532302d79656c6c6f77)[![Supported architectures: x86-64 or ARM64](https://camo.githubusercontent.com/54a163b414befd99385ff5a7043fb278715928b8109a64a5966689f798faddd0/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6172636869746563747572652d7838362d2d363425323025374325323041524d36342532302d73696c766572)](https://camo.githubusercontent.com/54a163b414befd99385ff5a7043fb278715928b8109a64a5966689f798faddd0/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6172636869746563747572652d7838362d2d363425323025374325323041524d36342532302d73696c766572)[![License](https://camo.githubusercontent.com/7d638a21d7dba3ad4ed85a59d0ac615d894f539e61c60bf9e3a6b19356a55be9/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f4e6f69736542794e6f727468776573742f7068702d737078)](https://github.com/NoiseByNorthwest/php-spx/blob/master/LICENSE)

[![Buy Me A Coffee](https://camo.githubusercontent.com/9f44ce2dc3b3eecdd02598900866ffc518801df1932849703dae1e5ce5031070/68747470733a2f2f7777772e6275796d6561636f666665652e636f6d2f6173736574732f696d672f637573746f6d5f696d616765732f6f72616e67655f696d672e706e67)](https://www.buymeacoffee.com/noisebynw)

[Click here for a live demo of the analysis screen](https://noisebynorthwest.github.io/php-spx/demo/report.html?key=spx-full-20191229_175636-06d2fe5ee423-3795-233665123)

[![Showcase](https://github.com/NoiseByNorthwest/NoiseByNorthwest.github.io/raw/d8a90827d6eb256f49d580de448b6b6fad4119ac/php-spx/doc/as.apng)](https://github.com/NoiseByNorthwest/NoiseByNorthwest.github.io/blob/d8a90827d6eb256f49d580de448b6b6fad4119ac/php-spx/doc/as.apng)

[![Showcase](https://github.com/NoiseByNorthwest/NoiseByNorthwest.github.io/raw/43e3ffe185a1dcec70e7c8ced36acfdf316bae65/php-spx/doc/fp1.gif)](https://github.com/NoiseByNorthwest/NoiseByNorthwest.github.io/blob/43e3ffe185a1dcec70e7c8ced36acfdf316bae65/php-spx/doc/fp1.gif)

SPX, which stands for *Simple Profiling eXtension*, is just another profiling extension for PHP. It differentiates itself from other similar extensions as being:

- totally free and confined to your infrastructure (i.e. no data leaks to a SaaS).
- very simple to use: just set an environment variable (command line) or switch on a radio button (web request) to profile your script. Thus, you are free of:
    - manually instrumenting your code (Ctrl-C a long running command line script is even supported).
    - using a dedicated browser extension or command line launcher.
- [multi metrics](#available-metrics) capable: 22 are currently supported (various time &amp; memory metrics, included files, objects in use, I/O...).
- able to collect data without losing context. For example Xhprof (and potentially its forks) aggregates data per caller / callee pairs, which implies the loss of the full call stack and forbids timeline or Flamegraph based analysis.
- shipped with its [web UI](#web-ui) which allows to:
    - enable / configure profiling for the current browser session
    - list profiled script reports
    - select a report for in-depth analysis, featuring these interactive visualizations:
        - timeline (scale to millions of function calls)
        - flat profile
        - Flamegraph

Requirements
------------

[](#requirements)

Platforms support is currently quite limited. Feel free to open an issue if your platform is not supported. Current requirements are:

- x86-64 or ARM64
- **GNU/Linux**, **macOS** or **FreeBSD**
- zlib dev package (e.g. zlib1g-dev on Debian based distros)
- PHP 5.4 to 8.5

Installation
------------

[](#installation)

### Prerequisites

[](#prerequisites)

- PHP development package (corresponding to your installed PHP version).
- zlib development package:
    - For Debian-based distros (including Ubuntu, Kubuntu...), just run: `sudo apt-get install zlib1g-dev`.
    - For Fedora-based distros (including CentOS, AlmaLinux, Rocky Linux...), just run: `sudo dnf install zlib-devel`.

### Install the extension

[](#install-the-extension)

#### Install via PIE

[](#install-via-pie)

```
pie install noisebynorthwest/php-spx
```

#### Install from source

[](#install-from-source)

```
git clone https://github.com/NoiseByNorthwest/php-spx.git
cd php-spx
git checkout release/latest
phpize
./configure
make
sudo make install
```

#### Activate &amp; configure SPX

[](#activate--configure-spx)

After installing SPX, add `extension=spx.so` to your *php.ini*, or in a dedicated *spx.ini* file created within the include directory. You may also want to override [default SPX configuration](#configuration) to be able to profile a web request, with [this one](#private-environment) for example for a local development environment.

### ZTS PHP (multi-thread)

[](#zts-php-multi-thread)

ZTS PHP is supported, with these extra limitations:

- a little overhead (theorically unnoticeable in most cases) is added when SPX is loaded, even if it is not enabled.
- Ctrl-C a CLI script will not make the possible profiling session to be properly finished.
- segfaults are more likely than for NTS PHP. In this regard, avoid more than ever mixing SPX with other instrumenting extensions (debuggers, profilers...).

Also, consider ZTS PHP support as still being in beta.

### Linux, PHP-FPM &amp; I/O stats

[](#linux-php-fpm--io-stats)

On GNU/Linux, SPX uses procfs (i.e. by reading files under `/proc` directory) to get some stats for the current process or thread. This is what is done under the hood when you select at least one of these metrics: `mor`, `io`, `ior` or `iow`.

But, on most PHP-FPM setups, you will have a permission issue preventing SPX to open a file under `/proc/self` directory. This is due to the fact that PHP-FPM master process runs as root when child processes run as another unprivileged user.

When this is the case, the `process.dumpable = yes` line must be added to the FPM pool configuration so that child processes will be able to read any file under `/proc/self`.

Development status
------------------

[](#development-status)

This is still **experimental**. API might change, features might be added or dropped, or development could be frozen.

You can still safely use it in a **non-production** environment.

Contributions are welcome but be aware of the experimental status of this project and **please follow the contribution rules** described here: [CONTRIBUTING.md](CONTRIBUTING.md)

Basic usage
-----------

[](#basic-usage)

### web request

[](#web-request)

Assuming a development environment with the configuration [described here](#private-environment) and your application is accessible via `http://localhost`.

Just open with your browser the following URL: `http://localhost/?SPX_KEY=dev&SPX_UI_URI=/` to access to the web UI [control panel](#control-panel).

*N.B.: `http://localhost/` must be served by a PHP script through standard web server feature like directory index or URL rewriting. The PHP script will however not be executed, SPX will intercept and disable its execution to serve its content in place.*

*If you see only a blank page then make sure to set `zlib.output_compression = 0` in your PHP configuration file*

You will then see the following form:

[![Showcase](https://github.com/NoiseByNorthwest/NoiseByNorthwest.github.io/raw/93baabbcba04223586d06756dbcecfbd6ec1293d/php-spx/doc/cp-form.png)](https://github.com/NoiseByNorthwest/NoiseByNorthwest.github.io/blob/93baabbcba04223586d06756dbcecfbd6ec1293d/php-spx/doc/cp-form.png)

Then switch on "Enabled". At this point profiling is enabled for the current domain and your current browser session through a set of dedicated cookies.

Profiling can also be triggered with Curl as shown in this example:

`curl --cookie "SPX_ENABLED=1; SPX_KEY=dev" http://localhost/`

*N.B.: You can also enable the profiling at INI configuration level via the `spx.http_profiling_enabled` [setting](#configuration), and therefore for all HTTP requests. However, keep in mind that using this setting on a high-traffic environment could quickly exhaust the storage device's capacity of the SPX's data directory.*

Then refresh the web request you want to profile and refresh the control panel to see the generated report in the list below the control panel form.

[![Showcase](https://github.com/NoiseByNorthwest/NoiseByNorthwest.github.io/raw/d8a90827d6eb256f49d580de448b6b6fad4119ac/php-spx/doc/cp-list2.png)](https://github.com/NoiseByNorthwest/NoiseByNorthwest.github.io/blob/d8a90827d6eb256f49d580de448b6b6fad4119ac/php-spx/doc/cp-list2.png)

Then click on the report in the list and enjoy the [analysis screen](#analysis-screen).

### Command line script

[](#command-line-script)

#### Instant flat profile

[](#instant-flat-profile)

Just prepend your command line with `SPX_ENABLED=1` to trigger profiling. You will get the flat profile printed on STDERR at the end of the execution, even if you abort it by hitting Ctrl-C, as in the following example:

```
$ SPX_ENABLED=1 composer update
Loading composer repositories with package information
Updating dependencies (including require-dev)
^C
*** SPX Report ***

Global stats:

  Called functions    :    27.5K
  Distinct functions  :      714

  Wall time           :    7.39s
  ZE memory           :   62.6MB

Flat profile:

 Wall time           | ZE memory           |
 Inc.     | *Exc.    | Inc.     | Exc.     | Called   | Function
----------+----------+----------+----------+----------+----------
  101.6ms |  101.6ms |   41.8MB |   41.8MB |       12 | Composer\Json\JsonFile::parseJson
   53.6ms |   53.6ms |     544B |     544B |        4 | Composer\Cache::sha256
    6.91s |   41.5ms |   41.5MB |   -7.5MB |        4 | Composer\Repository\ComposerRepository::fetchFile
    6.85s |   32.3ms |   47.5MB |    5.4MB |        5 | 1@Composer\Repository\ComposerRepository::loadProviderListings
    7.8ms |    7.8ms |       0B |       0B |        4 | Composer\Cache::write
    1.1ms |    1.1ms |     -72B |     -72B |        1 | Composer\Console\Application::Composer\Console\{closure}
  828.5us |  828.5us |     976B |     976B |       12 | Composer\Util\RemoteFilesystem::findHeaderValue
  497.6us |  491.0us |  710.2KB |  710.2KB |        1 | Composer\Cache::read
    2.4ms |  332.6us |   20.9KB | -378.8KB |       34 | 3@Symfony\Component\Finder\Iterator\FilterIterator::rewind
  298.9us |  298.9us |    2.2KB |    2.2KB |       47 | Symfony\Component\Finder\Iterator\FileTypeFilterIterator::accept
```

N.B.: Just add `SPX_FP_LIVE=1` to enable the live refresh of the flat profile during script execution.

#### Generate profiling report for the web UI

[](#generate-profiling-report-for-the-web-ui)

You just have to specify `SPX_REPORT=full` to generate a report available via the web UI:

```
SPX_ENABLED=1 SPX_REPORT=full ./bin/console cache:clear
```

#### Handle long-living / daemon processes

[](#handle-long-living--daemon-processes)

If your CLI script is long-living and/or daemonized (e.g. via supervisord), profiling its whole lifespan could be meaningless. This is especially true in case of a service waiting for tasks to process.
To handle this case, SPX allows to disable the automatic start of profiling and exposes 2 userland functions, `spx_profiler_start(): void` &amp; `spx_profiler_stop(): ?string`, in order to respectively control the start and the end of the profiled spans.

Here is how you can instrument your script:

```
