To find which PHP function is causing high CPU usage, attach OpenResty XRay to the already-running PHP process — no recompiling and no restarting. Its Guided Analysis produces a CPU flame graph of the live process. In this case the hottest path was a preg_match call inside the processOrders business function, reached through Laravel’s callAction, pointing straight at a regular expression as the CPU bottleneck. Concerned about the overhead on a live PHP process? We measured it end to end.

Today I will show you another step-by-step guide for analyzing PHP applications with OpenResty XRay. We’ll quickly pinpoint the hottest code paths in an already-running PHP process. These code paths might take most of the CPU time of your applications. OpenResty XRay is a truly non-intrusive dynamic analysis tool that requires no installation of any special modules or plugins in the target application, no recompilation of the target application, and even no need to restart the running processes.

Problem: high CPU usage

Let’s run the top command to check the CPU usage. As shown, the php process consumes 100% of a CPU core.

top command showing a PHP process consuming 100% of a CPU core

Run the ps command to see the full command line for this process. We can see it is the standard PHP binary executable shipped with the Linux distribution.

ps command output showing the full PHP process command line

Find which PHP function is using the CPU

Let’s use OpenResty XRay to check out this unmodified process and figure out what’s going on in real time.

Open the OpenResty XRay web console, confirm you are on the machine running the hot PHP process (you can pick a different machine from the list if needed), and go to the “Guided Analysis” page. From the list of problem types, choose “High CPU usage”.

OpenResty XRay Guided Analysis page highlighting the High CPU usage problem type

Next, point the analysis at the PHP application and select the process consuming 100% of the CPU — the same one we saw earlier in top. OpenResty XRay can analyze multiple language levels at once, so we keep both the PHP and C/C++ levels selected and leave the maximum analyzing time at the default 300 seconds. Start the analysis; it runs successive rounds automatically, and after the first couple of rounds we have enough data, so we stop it and let it build the report.

The high CPU analysis report OpenResty XRay automatically generated for the PHP process

This is the problem type we are analyzing now: CPU.

The top of the report showing the diagnosed problem type is CPU

This is the #1 hottest PHP code path using the most CPU time, taking 56.2% of the CPU time:

The #1 hottest PHP code path in the report, taking 56.2% of the CPU time

The hottest function call is preg_match. It is PHP’s wrapper for regular expression matching:

The preg_match function highlighted in the code path

The processOrders function belongs to the business code:

The business-logic function processOrders highlighted in the code path

callAction is a method in the Laravel framework that invokes a specified action in a controller:

The Laravel callAction method highlighted in the code path

Hover the mouse over the green box of the processOrders function. The tooltip shows the full path of this PHP source file:

Tooltip showing the full path of the ProductServiceProvider.php source file for processOrders

The line number of this source line is 437:

Tooltip showing the source line number 437 for this line

Copy its source file path:

Clicking the copy icon to copy the full source file path of the function

Open its source file with the Vim editor and view the PHP code in this file. You can use any editor you like:

Opening the ProductServiceProvider.php source file with vim in a terminal

Following the advice from OpenResty XRay, jump to line 437:

Jumping to source line 437 in vim, highlighting the preg_match call on that line

We can see the preg_match call matches the report. Because the regular expression is matched repeatedly inside a loop, we can precompile it to cut the CPU cost — a concrete, actionable optimization:

PHP source line 437 showing the preg_match call inside the processOrders loop

This source line sits inside the processOrders function:

The vim status line confirming line 437 is inside the processOrders function

Click “More” to see the details of this code path:

Clicking the More link to view further details of the code path

This hot code path is automatically inferred from this PHP-land CPU flame graph, which lays out where the process actually spends its CPU time:

PHP-land CPU flame graph showing the hottest code path in the running process

Below is a more detailed explanation and set of suggestions for the problem. It mentions the preg_match function we saw earlier and offers advice such as removing unnecessary middlewares and optimizing the regular expression (avoiding backtracking, using non-capturing groups, reducing greedy quantifiers):

The report’s Explanation and Suggestions section explaining the preg_match root cause and giving optimization advice

Let’s look at the C code path using the most CPU time. It takes 34.7% of the CPU time and mirrors the PHP-side path:

The #1 hottest C code path, taking 34.7% of the CPU time, with pcre2_match_8 as the hottest function

The pcre2_match_8 function is part of the PCRE2 library:

The PCRE2 library function pcre2_match_8 highlighted in the C code path

The php_pcre_match_impl function calls into PCRE2 to implement regular expression matching:

The php_pcre_match_impl function highlighted in the C code path

php_do_pcre_match implements the preg_match function. It matches a regular expression against a string:

The php_do_pcre_match function highlighted in the C code path

The zend_execute_scripts function is used to execute the PHP script. Clearly, this is similar to the PHP hot code path we just looked at. This confirms, from the C level, that the regular expression matching is the true CPU bottleneck:

The zend_execute_scripts function highlighted in the C code path, used to execute the PHP script

This is the same PHP profiling workflow we use for the sibling problem of a PHP process using too much memory, and for tracing PHP exceptions in production — always on live, unmodified processes.

Automatic analysis and reports

OpenResty XRay can also monitor online processes automatically and generate analysis reports. Go to the “Insights” page:

The Insights page entry highlighted in the left navigation bar

On the “Insights” page you can find automatic reports for daily and weekly periods — so you don’t even have to run Guided Analysis yourself:

OpenResty XRay Insights page with automatic daily and weekly analysis reports

Of course, Guided Analysis remains useful for application development and demonstration purposes:

Example of an automatic daily analysis report shown on the Insights page

Frequently Asked Questions

Why is my PHP process using 100% CPU?

A PHP process pinned at 100% CPU is CPU-bound — burning cycles in hot code rather than waiting on I/O. In this case the culprit was a preg_match regular expression matched repeatedly inside a loop in the processOrders function. Attaching OpenResty XRay to the live process and reading its CPU flame graph reveals exactly which function is burning the CPU, without recompiling or restarting anything.

How do I find which PHP function is causing high CPU usage?

Attach OpenResty XRay to the already-running PHP process and start a Guided Analysis for “High CPU usage”. It reads the process in real time, so you don’t instrument, recompile, or restart your application. The result is a report and a CPU flame graph that ranks the hottest PHP code paths and points you to the exact function, source file, and line number responsible.

Can preg_match or regular expressions cause high CPU in PHP?

Yes. preg_match runs on the PCRE2 engine, and matching a regular expression repeatedly — for example inside a loop — can dominate CPU time. In this article the hottest PHP path was preg_match inside processOrders, and the hottest C path (pcre2_match_8 via php_do_pcre_match) confirmed it. Precompiling the expression so it isn’t rebuilt on every iteration is a straightforward fix.

What is OpenResty XRay

OpenResty XRay is a dynamic-tracing product that automatically analyzes your running applications to troubleshoot performance problems, behavioral issues, and security vulnerabilities with actionable suggestions. Under the hood, OpenResty XRay is powered by our Y language targeting various runtimes like Stap+, eBPF+, GDB, and ODB, depending on the contexts.

If you like this tutorial, please subscribe to this blog site and/or our YouTube channel. Thank you!

About The Author

Yichun Zhang (Github handle: agentzh), is the original creator of the OpenResty® open-source project and the CEO of OpenResty Inc..

Yichun is one of the earliest advocates and leaders of “open-source technology”. He worked at many internationally renowned tech companies, such as Cloudflare, Yahoo!. He is a pioneer of “edge computing”, “dynamic tracing” and “machine coding”, with over 22 years of programming and 16 years of open source experience. Yichun is well-known in the open-source space as the project leader of OpenResty®, adopted by more than 40 million global website domains.

OpenResty Inc., the enterprise software start-up founded by Yichun in 2017, has customers from some of the biggest companies in the world. Its flagship product, OpenResty XRay, is a non-invasive profiling and troubleshooting tool that significantly enhances and utilizes dynamic tracing technology. And its OpenResty Edge product is a powerful distributed traffic management and private CDN software product.

As an avid open-source contributor, Yichun has contributed more than a million lines of code to numerous open-source projects, including Linux kernel, Nginx, LuaJIT, GDB, SystemTap, LLVM, Perl, etc. He has also authored more than 60 open-source software libraries.