If you find Xdebug useful, please consider supporting the project.

Garbage Collection Statistics

Xdebug's built-in garbage collection statistics profiler allows you to find out when the PHP internal garbage collector triggers, how many variables it was able to clean up, how long it took, and how how much memory was actually freed.

Introduction

Garbage Collection (GC) in PHP can have a serious impact on memory and performance, so understanding when it is triggered and how efficient each run is, allows you to optimise your programs. The PHP Engine does not provide a mechanism to gather statistics about garbage collection, but Xdebug now does.

For the time being, the garbage collection statistics are collected in a human readable, tabular format only, because there are no tools for this kind of report that we could generate machine readable output for. Future versions may include exports in other formats to allow machine processing.

Usage

There are two approaches to start collecting the GC statistics with two different use-cases.

By Settings

The first is entirely via INI settings and the primary use-case is to collect statistics for indiviual CLI script runs (where GC is often an issue).

php -dxdebug.mode=gcstats -dxdebug.start_with_request=yes your_script.php

If you wish to collect the garbage collection statistics for every script that you execute, you can set the xdebug.mode=gcstats and xdebug.start_with_request=yes INI settings on the system or directory-level. Be aware that activating the collection globally will produce an output file for every executed script, even if the garbage collector didn't run.

By Calling a Function

The second approach to starting collection is to call the function xdebug_start_gcstats() directly in your PHP script. This gives you more control over when statistics collection is started.

You can stop collection for both INI and function based approaches by calling xdebug_stop_gcstats().

Output

GC status file are written to the directory configured with xdebug.output_dir. The file name can be configured with xdebug.xdebug.gc_stats_output_name.

The output format of Garbage Collection statistics is a tabular human readable text output.

Garbage Collection Report
version: 1
creator: xdebug 2.6.0 (PHP 7.2.0)

Collected | Efficiency% | Duration | Memory Before | Memory After | Reduction% | Function
----------+-------------+----------+---------------+--------------+------------+---------
    10000 |    100.00 % |  0.00 ms |       5539880 |       579880 |    79.53 % | bar
    10000 |    100.00 % |  0.00 ms |       5540040 |       580040 |    79.53 % | Garbage::produce
     4001 |     40.01 % |  0.00 ms |       2563048 |       578968 |    77.41 % | gc_collect_cycles

The header contains the version of the report and the version of Xdebug that generated it.

The table itself then contains one row for each garbage collection run each with 7 reported variables:

For details on how PHPs garbage collection works see the PHP manuals chapter on Garbage Collection.

Related Settings and Functions

Settings


string xdebug.gc_stats_output_name = gcstats.%p #

This setting determines the name of the file that is used to dump garbage collection statistics into. The setting specifies the format with format specifiers, very similar to sprintf() and strftime(). There are several format specifiers that can be used to format the file name.

See the xdebug.trace_output_name documentation for the supported specifiers.


string xdebug.log = #

Configures Xdebug's log file.

Xdebug will log to this file all file creations issues, Step Debugging connection attempts, failures, and debug communication.

Enable this functionality by setting the value to a absolute path. Make sure that the system user that PHP runs at (such as www-data if you are running with Apache) can create and write to the file.

The file is opened in append-mode, and will therefore not be overwritten by default. There is no concurrency protection available.

The log file will include any attempt that Xdebug makes to connect to an IDE:

[2693358] Log opened at 2020-09-02 07:19:09.616195
[2693358] [Step Debug] INFO: Connecting to configured address/port: localhost:9003.
[2693358] [Step Debug] ERR: Could not connect to debugging client. Tried: localhost:9003 (through xdebug.client_host/xdebug.client_port) :-(
[2693358] [Profiler] ERR: File '/foo/cachegrind.out.2693358' could not be opened.
[2693358] [Profiler] WARN: /foo: No such file or directory
[2693358] [Tracing] ERR: File '/foo/trace.1485761369' could not be opened.
[2693358] [Tracing] WARN: /foo: No such file or directory
[2693358] Log closed at 2020-09-02 07:19:09.617510

It includes the opening time (2020-09-02 07:19:09.616195), the IP/Hostname and port Xdebug is trying to connect to (localhost:9003), and whether it succeeded (Connected to client :-)). The number in brackets ([2693358]) is the Process ID.

It includes:

[2693358]
process ID in brackets
2020-09-02 07:19:09.616195
opening time

For Step Debugging:

INFO: Connecting to configured address/port: localhost:9003.
ERR: Could not connect to debugging client. Tried: localhost:9003 (through xdebug.client_host/xdebug.client_port) :-(

For Profiling:

ERR: File '/foo/cachegrind.out.2693358' could not be opened.
WARN: /foo: No such file or directory

For Function Trace:

ERR: File '/foo/trace.1485761369' could not be opened.
WARN: /foo: No such file or directory

All warnings and errors are described on the Description of errors page, with detailed instructions on how to resolve the problem, if possible. All errors are always logged through PHP's internal logging mechanism (configured with error_log in php.ini). All warnings and errors also show up in the diagnostics log that you can view by calling xdebug_info().

Step Debugger Communication

The debugging log can also log the communication between Xdebug and an IDE. This communication is in XML, and starts with the <init XML element:

<init
    xmlns="urn:debugger_protocol_v1" xmlns:xdebug="https://xdebug.org/dbgp/xdebug"
    fileuri="file:///home/httpd/www.xdebug.org/html/router.php"
    language="PHP" xdebug:language_version="7.4.11-dev"
    protocol_version="1.0" appid="2693358" idekey="XDEBUG_ECLIPSE">
        <engine version="3.0.0-dev"><![CDATA[Xdebug]]></engine>
        <author><![CDATA[Derick Rethans]]></author>
        <url><![CDATA[https://xdebug.org]]></url>
        <copyright><![CDATA[Copyright (c) 2002-2020 by Derick Rethans]]></copyright>
</init>

The fileuri attribute lists the entry point of your application, which can be useful to compare to breakpoint_set commands to see if path mappings are set-up correctly.

Beyond the <init element, you will find the configuration of features:

<- feature_set -i 4 -n extended_properties -v 1
-> <response
       xmlns="urn:debugger_protocol_v1" xmlns:xdebug="https://xdebug.org/dbgp/xdebug"
       command="feature_set" transaction_id="4" feature="extended_properties" success="1">
   </response>

And continuation commands:

<- step_into -i 9
-> <response
       xmlns="urn:debugger_protocol_v1" xmlns:xdebug="https://xdebug.org/dbgp/xdebug"
       command="step_into" transaction_id="9"
       status="break" reason="ok">
           <xdebug:message filename="file:///home/httpd/www.xdebug.org/html/router.php" lineno="3">
           </xdebug:message>
   </response>

You can read about DBGP - A common debugger protocol specification at its dedicated documation page.

The xdebug.log_level setting controls how much information is logged.

Note: Many Linux distributions now use systemd, which implements private tmp directories. This means that when PHP is run through a web server or as PHP-FPM, the /tmp directory is prefixed with something akin to:

/tmp/systemd-private-ea3cfa882b4e478993e1994033fc5feb-apache.service-FfWZRg

integer xdebug.log_level = 7 #

Configures which logging messages should be emitted.

The following levels are supported:

LevelNameExample
1ErrorsConnection errors
3WarningsConnection warnings
5CommunicationProtocol messages
7InformationInformation while connecting
10DebugBreakpoint resolving information

Errors are also logged through PHP's internal logging mechanism (configured with error_log in php.ini).

Warnings and errors show up in the diagnostics log that you can view by calling xdebug_info().


string xdebug.mode = display #

This setting controls which Xdebug features are enabled.

The following values are accepted:

off
Nothing is enabled. Xdebug does no work besides checking whether functionality is enabled. Use this setting if you want close to 0 overhead.
develop
Enables Development Aids including the overloaded var_dump().
coverage
Enables Code Coverage Analysis to generate code coverage reports, mainly in combination with PHPUnit.
debug
Enables Step Debugging. This can be used to step through your code while it is running, and analyse values of variables.
gcstats
Enables Garbage Collection Statistics to collect statistics about PHP's Garbage Collection Mechanism.
profile
Enables Profiling, with which you can analyse performance bottlenecks with tools like KCacheGrind.
trace
Enables the Function Trace feature, which allows you record every function call, including arguments, variable assignment, and return value that is made during a request to a file.

string xdebug.output_dir = /tmp #

The directory where Xdebug will write tracing, profiling, and garbage collection statistics to. This directory needs to be writable for the system user with which PHP is running.

This setting can be changed in php.ini, .htaccess (and equivalent files), and within a PHP file with ini_set().

In some cases (when profiling, or when xdebug.start_with_request=yes with tracing), Xdebug creates the file before the script runs. In that case, changes made through ini_set() will not be taken into account.


string xdebug.start_with_request = default #

A Function Trace, Garbage Collection Statistics, Profiling, or Step Debugging can be activated at the start of a PHP request. Whether this happens depends on the value of this setting:

yes

The functionality starts when the PHP request starts, and before any PHP code is run.

For example xdebug.mode=trace and xdebug.start_with_request=yes starts a Function Trace for the whole request.

no

The functionality does not get activated when the request starts.

You can still start a Function Trace with xdebug_start_trace(), Step Debugging with xdebug_break(), or Garbage Collection Statistics with xdebug_start_gcstats().

trigger

The functionality only gets activated when a specific trigger is present when the request starts.

The name of the trigger is XDEBUG_TRIGGER, and Xdebug checks for its presence in either $_ENV (environment variable), $_GET or $_POST variable, or $_COOKIE (HTTP cookie name).

There is also a legacy fallback to a functionality specific trigger name: XDEBUG_PROFILE (for Profiling), XDEBUG_TRACE (for a Function Trace), and XDEBUG_SESSION (for Step Debugging).

Debug session management for Step Debugging is also still available through XDEBUG_SESSION_START.

With xdebug.trigger_value you can control which specific trigger value will activate the trigger. If xdebug.trigger_value is set to an empty string, any value will be accepted.

default

The default value depends on xdebug.mode:

  • debug: trigger

  • gcstats: no

  • profile: yes

  • trace: trigger

Functions


xdebug_get_gc_run_count() : int #

Returns the number of garbage collection runs that have been triggered so far

The function returns the number of times the garbage collection has been triggered in the currently running script.

This number is available even if the xdebug.start_with_request INI setting is not set to yes.


xdebug_get_gc_total_collected_roots() : int #

Returns the number of variable roots that have been collected so far

The function returns the number of variable roots that the garbage collection has collected during all runs of the garbage collector in the current script.

This number is available even if the xdebug.start_with_request INI setting is not set to yes.


xdebug_get_gcstats_filename() : mixed #

Returns the garbage collection statistics filename

Returns the name of the file which is used to save garbage collection information to, or false if statistics collection is not active.


xdebug_start_gcstats( ?string $gcstatsFile = null ) : mixed #

Start the collection of garbage collection statistics

Start tracing garbage collection attempts from this point to the file in the gcstatsFile parameter. If no filename is given, then garbage collection stats file will be placed in the directory as configured by the xdebug.output_dir setting.

In case a file name is given as first parameter, the name is relative to the current working directory. This current working directory might be different than you expect it to be, so please use an absolute path in case you specify a file name. Use the PHP function getcwd() to figure out what the current working directory is.

If xdebug.start_with_request=yes, then filename depends on the xdebug.gc_stats_output_name setting.

The full path and filename to which Xdebug collects statistics into is returned from this function. This will be either the filename you pass in, or the auto generated filename if no filename has been passed in.


xdebug_stop_gcstats() : string #

Stops the current garbage collection statistics collection

Stop garbage collection statistics collection and closes the output file.

The function returns the filename of the file where the statistics were written to.