In 2012, you just started learning PHP. At that time, the application of PHP was very simple, there were not too many complex design modes, such as dependent injection, factory mode, which were few. Reflection API was just coming out at that time. A PHP application was some script files that packed the front-end code. Just because PHP was simple and reliable, the learning cost was very low, PHP became very popular in those years. You can quickly read PHP codes written by others, no matter how bad they are. I had just graduated at that time with my proficiency in PHP, I could easily get 7,800 salaries in the top 34 cities, plus thorough research into the source code of the major frameworks (Tp, Ci, Yii, Cphalcon) at that time, and thought I had touched the ceiling of PHP. Later, PHP was written less and less in cities, using a set of framework written by Swoole.
However, PHP now accounts for 90% of the company's share and is basically Laravel/Lumen apps, which makes it difficult for me to keep optimizing performance. Laravel uses a large number of design patterns, dynamic injection, many times only at runtime can we know the specific object instances, it is difficult to determine the running state of the service only by looking at the source code. Therefore, flame graphs and visual call stacks are important for performance analysis, and they can be very intuitive and accurate to see the various time-consuming.
In PHP, we can focus on two levels of flame graphs: the PHP core and the PHP Zend call stack. The former is a time consuming flame graph capturing system calls, and the latter is a time consuming flame graph of Zend VM. The two flame graphs are shared below.
Running Environment
Operating System (Arch Linux)
# neofech -` russell@T14 .o+` ----------- `ooo/ OS: Arch Linux x86_64 `+oooo: Host: NBLK-WAX9X M1040 `+oooooo: Kernel: 5.14.14-arch1-1 -+oooooo+: Uptime: 1 hour, 15 mins `/:-:++oooo+: Packages: 852 (pacman) `/++++/+++++++: Shell: zsh 5.8 `/++++++++++++++: Resolution: 1920x1080 `/+++ooooooooooooo/` DE: Plasma 5.23.2 ./ooosssso++osssssso+` WM: KWin .oossssso-````/ossssss+` WM Theme: Breeze -osssssso. :ssssssso. Theme: Breeze Light [Plasma], Breeze [GTK2/3] :osssssss/ osssso+++. Icons: Uos-fulldistro-icons [Plasma], Uos-fulldi /ossssssss/ +ssssooo/- Terminal: konsole `/ossssso+/:- -:/+osssso+- Terminal Font: Hack 10 `+sso+:-` `.-/+oso: CPU: AMD Ryzen 5 3500U with Radeon Vega Mobile G `++:. `-/+/ GPU: AMD ATI 03:00.0 Picasso .` `/ Memory: 1928MiB / 6880MiB
PHP Version
# php -v PHP 7.4.23 (cli) (built: Sep 19 2021 12:07:04) ( NTS ) Copyright (c) The PHP Group Zend Engine v3.4.0, Copyright (c) Zend Technologies with Xdebug v3.1.1, Copyright (c) 2002-2021, by Derick Rethans
There's nothing to ask for, as long as it's not under version 5.6.
Laravel version
# php artisan -V Laravel Framework 8.61.0
perf version
# perf -v perf version 5.14.g7d2a07b76933
Download flamegraph
git clone https://github.com/brendangregg/FlameGraph.git cd FlameGraph # This step is to inject FlameGraph into the path of the executable file system so that the tools inside can be executed directly below. export PATH=`pwd`:$PATH
This tool is critical to capture the time-consuming system calls through perf and generate a flame graph.
Grab PHP Kernel Flame Graph
Find the PHP process ID first, then grab it with the following command
# Grab PID for 7959 process for 60 seconds perf record -F 99 -p 7959 -g -- sleep 30
Export Stack
perf script > out.perf
Generate Fold stacks file
stackcollapse-perf.pl out.perf > out.folded
Generate Flame Graph
flamegraph.pl out.folded > php-zend-flame-graph.svg
To see the effect, the svg format picture can be filtered by clicking on the flame bar (open a new tab):
Grab Zend VM Time-consuming Flame Graph
This flame graph generation relies on xdebug and different xdebug versions use different configurations. Configuration instructions can be viewed directly from the xdebug package configuration file or above Github Look.
Xdebug3 configuration:
zend_extension=xdebug xdebug.mode=trace xdebug.start_with_request=trigger xdebug.trigger_value=StartProfileForMe xdebug.trace_output_name = xdebug.trace.%t.%s xdebug.output_dir = /tmp xdebug.trace_format=1
Xdebug2 configuration:
xdebug.trace_output_name = xdebug.trace.%t.%s xdebug.trace_enable_trigger = 1 xdebug.trace_output_dir = /tmp xdebug.trace_enable_trigger_value = "<secret key>" xdebug.trace_format=1
Request interface url to get php stack data curl http://youdomain.com?XDEBUG_ TRACE=<secret key>. The trace file starts with xdebug.tarce in the / tmp directory.
Convert stack data (if stackcollapse-xdebug.php does not exist, note the download flamegraph description above):
stackcollapse-xdebug.php /tmp/xdebug.trace.1635786267._data_workspaces_study_laravel-framework_laravel_server_php.xt
If the xdebug trace file is in gz format, convert it:
# The parameter `-dk'means to unzip and preserve the source file. gzip -dk /tmp/xdebug.trace.1635786267._data_workspaces_study_laravel-framework_laravel_server_php.xt.gz
Convert stack data
stackcollapse-xdebug.php xdebug.trace.1635786267._data_workspaces_study_laravel-framework_laravel_server_php.xt > out.folded
Generate Flame Graph
flamegraph.pl out.folded > laravel-flame-graph.svg
To see the effect, the svg format picture can be filtered by clicking on the flame bar (open a new tab):