Debug a slow Wordpress site

A few days ago my colleague asked me to help him figure out why his Wordpress website was running so slow. Everything seemed fine, the CPU was not busy, the memory was not used much. It was not the network issue because its ping time was very fast. The MySQL database was not slow either. So it was hard for me to debug.

The site returned 504 error initially, but it sometimes could load the page (after a long wait). I checked the Nginx error log and found that the upstream connection was not responded. So it must be something wrong with the PHP code.

I tried many ways which I found on the internet but no success. Most of them were about increasing the timeout or the execution time. By doing that, the page could load but it was still super slow (it loaded in > 1min).

When I sat quietly for a while to think, I realized that plugins could be the issue. There could not be any reason a Wordpress could be that slow unless there were some new extensions (or plugins) working abnormally. But how could I find out which plugin is working well and which one is not? I could in theory turn them off one by one but it would be very time consuming.

Luckily there is a config in PHP-FPM to output slow execution script to a log file. By default, this feature was disabled so nothing was logged. I checked the PHP-FPM config file and changed two configs

slowlog = /var/log/php-fpm/www-slow.log
request_slowlog_timeout = 10s

After restarting php-fpm service and reloading the page, I could clearly see which script was causing the issue. Here was the log

[0x00007f1516a17770] curl_exec() /var/www/html/wp-includes/Requests/Transport/cURL.php:162
[0x00007f1516a176a0] request() /var/www/html/wp-includes/class-requests.php:379
[0x00007f1516a17590] request() /var/www/html/wp-includes/class-http.php:370
[0x00007f1516a173f0] request() /var/www/html/wp-includes/class-http.php:589
[0x00007f1516a17330] post() /var/www/html/wp-includes/http.php:187
[0x00007f1516a17280] wp_remote_post() /var/www/html/wp-content/plugins/akismet/class.akismet.php:1107
[0x00007f1516a170e0] http_post() /var/www/html/wp-content/plugins/akismet/class.akismet.php:64
[0x00007f1516a17040] check_key_status() /var/www/html/wp-content/plugins/akismet/class.akismet.php:68
[0x00007f1516a16f90] verify_key() /var/www/html/wp-content/plugins/jetpack/class.jetpack.php:7082
[0x00007f1516a16ef0] is_akismet_active() /var/www/html/wp-content/plugins/jetpack/modules/sharedaddy/sharing-service.php:72
[0x00007f1516a16d40] get_all_services() /var/www/html/wp-content/plugins/jetpack/modules/sharedaddy/sharing-service.php:188
[0x00007f1516a16c00] get_blog_services() /var/www/html/wp-content/plugins/jetpack/_inc/lib/class.core-rest-api-endpoints.php:2516
[0x00007f1516a16ab0] prepare_options_for_response() /var/www/html/wp-content/plugins/jetpack/_inc/lib/core-api/class.jetpack-core-api-module-endpoints.php:404
[0x00007f1516a16950] get_all_options() /var/www/html/wp-content/plugins/jetpack/_inc/lib/admin-pages/class.jetpack-react-page.php:337
[0x00007f1516a168a0] get_flattened_settings() /var/www/html/wp-content/plugins/jetpack/_inc/lib/admin-pages/class.jetpack-react-page.php:287
[0x00007f1516a16680] page_admin_scripts() /var/www/html/wp-content/plugins/jetpack/_inc/lib/admin-pages/class.jetpack-admin-page.php:117
[0x00007f1516a165f0] admin_scripts() /var/www/html/wp-includes/class-wp-hook.php:286
[0x00007f1516a16500] apply_filters() /var/www/html/wp-includes/class-wp-hook.php:310
[0x00007f1516a16480] do_action() /var/www/html/wp-includes/plugin.php:453
[0x00007f1516a16360] do_action() /var/www/html/wp-admin/admin-header.php:118

Aha, so the curl_exec was the issue. It seems like the curl request was not succesful and the slowness was because the script had to wait for the response from that curl request. Going a bit further in the stacktrace, we can see that Akismet and Jetpack were two plugins using that curl_exec(). I went to Wordpress admin (which was also very slow) and disabled these two plugins, the site become fast again.

It is important to know that this might be a piece of cake for an experienced PHP developer, but I am not that guy. I am a Rails guy who can play around with the server, that's why I am happy to resolve partly the issue. I did not know why curl request failed to load the resource, perhaps something was wrong with the network. So next time, if you see some issue with the PHP site, remember to turn on the slowlog config so that you know what is going on.