Another monthly update where I explain what happened with Xdebug development in this past month. These will be published on the first Tuesday after the 5th of each month. Patreon and GitHub supporters will get it earlier, on the first of each month. You can become a patron to support my work on Xdebug. If you are leading a team or company, then it is also possible to support Xdebug through a subscription.
In July, I worked on Xdebug for about 100 hours, with funding being around 70 hours. I worked mostly on the following things:
I spend nearly all of my time improving performance this month, with some help by Michael Voříšek for the profiler feature. Some of this work I have done live through Twitch where I stream (almost) every Monday at 15:30 BST (14:30 UTC/10:30 EDT). Past sessions are available on Vimeo.
In order to find out what can be improved I profiled Xdebug running various workloads. I have selected the following workloads per Xdebug mode
If you have any specific one you’d like to see added, please let me know and I’ll see whether I have CPU cycles for it—running composer update for Pimcore under the C profiler Valgrind takes 2½ hours per run!
In any case, the profiling found out the following possible improvements:
Use zend_string for filenames and variable names
Most of Xdebug was written before PHP 7, and when updating Xdebug to work with both PHP 5 and PHP 7 certain PHP 5 APIs, wrapped in macros to make it work with PHP 7, remained in use by Xdebug. When dropping PHP 5 support, I did not update these APIs to use the PHP 7 variant. One of these APIs is that in PHP 5, strings were often passed around as a char string, size_t len pair. PHP 7 introduced a new data type zend_string str which encapsulates both elements of the pair, and also introduced reference counting for zend_string s, which reduces the need for duplication of memory. This gave about a ~2% performance boost to Wall Time (the time passage as indicated by a clock), and about a 5% reduction in CPU instructions.
Switch xdebug_sprintf to a new xdebug_str_add_fmt
Xdebug often needs to convert data into a single string, for either writing to file or network, storing function names with arguments in memory, or display purposes. It uses an API xdebug_sprintf which allocates new memory and formats the string according to format specifiers. Often it needs to add this to a xdebug_str buffer that makes up a longer piece of text. After it has added it to that buffer, it frees the allocated memory again.
By creating a new API that can add a formatted string to an xdebug_str buffer, I managed to reduce the amount of memory allocations and frees dramatically. This gave a 10-15% Wall Time performance boost, and a 10-25% reduction in CPU instructions.
Use a vector instead of a list for the stack
Xdebug’s internals contain a stack of all the functions that are called. Every time a new function is called, a new stack level is allocated, and when the function ends this stack element is freed up. In applications which call a lot of small functions, such as Com