How to Benchmark PHP Performance on Your Webdock Server
Last updated: August 29th 2024
Assessing the performance of your PHP application is crucial for ensuring it operates efficiently on your web server. This process involves measuring execution times and resource consumption to identify bottlenecks, optimize code, and make informed decisions regarding server configurations.
You can gain insightful perspectives into your application's performance with the appropriate tools and techniques. One highly effective tool for this purpose is the PHP Benchmark Script developed by Sergio Brighenti.
This article will walk you through the steps of utilizing this script to benchmark your PHP application, including how to incorporate MySQL benchmarks for a thorough analysis.
Why Benchmark?
Before exploring the specifics of the PHP Benchmark Script, it’s essential to grasp what benchmarking entails and its significance. In software development, benchmarking means measuring the performance of a system or application. This can include evaluating various aspects, such as execution time, memory usage, and response times under different loads.
Benchmarking aims to detect performance bottlenecks and understand how well an application performs under various conditions. It enables developers to make data-driven decisions regarding optimizations and enhancements.
These are some of the reasons you should benchmark your servers:
- Identify Bottlenecks: By measuring execution times for different segments of your application, you can identify where slowdowns occur. This information is vital for optimizing code and enhancing overall performance.
- Compare Performance: Benchmarking allows you to compare the performance of different PHP versions or server configurations. This is especially beneficial when upgrading or migrating applications.
- Resource Utilization: Understanding how your application uses server resources aids in optimizing server configurations for improved performance and cost-effectiveness.
- User Experience: Faster applications contribute to better user experiences. Optimizing performance through benchmarking can increase customer satisfaction and retention.
- Performance Regression Testing: Regular benchmarking helps ensure that new code changes do not adversely affect performance, allowing you to maintain high standards over time.
What is PHP Benchmark Script?
While there are plenty of benchmarking scripts in the market, we like the PHP Benchmark Script because it is a straightforward, no-nonsense, yet powerful tool for comparing the raw performance of different PHP versions and server setups.
You can find the script on GitHub. It enables you to measure execution times for various control flows and functions, offering insight into how well your application operates under different conditions. Here are some features of the script that stand out:
- Execution Time Measurement: The script calculates how long various operations take, enabling you to identify sluggish parts of your application.
- Custom Benchmarking: You can create custom benchmarks tailored to your specific requirements, providing flexibility in testing.
- Multiple Tests: The script supports additional tests, including file I/O and MySQL performance, facilitating comprehensive analysis.
Getting Started with the PHP Benchmark Script
To begin with, download the PHP Benchmark Script to your server. You can either run it directly from SSH:
$ wget https://raw.githubusercontent.com/SergiX44/php-benchmark-script/master/bench.php
You can also download bench.php from GitHub and upload it to your server’s document root using an FTP client or SSH. Once the bench.php script is placed on your server, run the command:
$ php bench.php
The results may be something like:
------------------------------------------------------- | PHP BENCHMARK SCRIPT v.2.0 by @SergiX44 | ------------------------------------------------------- PHP............................................. 8.3.10 Platform......................................... Linux Arch............................................ x86_64 Server...................................... mysqlbench Max memory usage.................................. 512M OPCache status................................ disabled OPCache JIT....................... disabled/unavailable PCRE JIT....................................... enabled XDebug extension.............................. disabled Difficulty multiplier............................... 1x Started at..................... 27/08/2024 20:28:55.483 ------------------------------------------------------- math.......................................... 0.2478 s loops......................................... 0.1978 s ifelse........................................ 0.3773 s switch........................................ 0.3393 s string........................................ 0.5775 s array......................................... 1.0332 s regex......................................... 0.3602 s is_{type}..................................... 0.3528 s hash.......................................... 0.1736 s json.......................................... 0.3661 s ------------------------------------------------------- Total time.................................... 4.0255 s Peak memory usage................................ 2 MiB
Let’s take a quick look at what each pointer means:
- PHP Version: Indicates the version of PHP running on the server (e.g., 8.3.10). It affects performance and available features.
- Platform: The operating system on which PHP is running (e.g., Linux). This can influence compatibility and performance.
- Architecture: This refers to the system architecture (e.g., x86_64), which indicates whether it’s 32-bit or 64-bit, which can affect memory handling and performance.
- Server: The name of the server (e.g., mysqlbench) which is just a label and does not affect benchmarking directly.
- Max Memory Usage: PHP's maximum amount of memory (e.g., 512M). This is important for resource-intensive scripts.
- OPCache Status: Indicates whether the OPcache (a PHP caching engine) is enabled or disabled. Enabling it can improve performance by caching compiled script bytecode.
- OPCache JIT: Shows if Just-In-Time compilation is available for OPcache. This can further enhance performance.
- PCRE JIT: Indicates if the PCRE (Perl Compatible Regular Expressions) Just-In-Time compilation is enabled, which can speed up regex operations.
- XDebug Extension: Indicates if the XDebug debugging tool is enabled. While it provides useful debugging features, it can slow down performance.
- Difficulty Multiplier: A factor indicating how the benchmark's performance is scaled; typically set to 1x for standard testing.
- Started At: The timestamp when the benchmark started, useful for tracking and logging purposes.
- Math, Loops, IfElse, Switch, String, Array, Regex, Is_{type}, Hash, JSON: These are individual benchmarks that measure the time taken to perform specific operations in PHP. Each entry shows the time in seconds it took to complete that particular task.
- Total Time: The overall time taken to run all the benchmark tests combined (e.g., 4.0255 s).
- Peak Memory Usage: The maximum amount of memory used during the benchmark test (e.g., 2 MiB), indicating how resource-intensive the operations were.
The benchmark script allows you to change the difficulty multiplier to adjust the intensity of tests. You can do this by passing the --multiplier parameter as follows:
$ php bench.php --multiplier=2
This parameter increases the number of iterations for each test, which can be beneficial for stress-testing your server.
When you're running the PHP Benchmark Script, it's important to recognize the differences in how OPcache behaves in the command line interface (CLI) versus a web server environment. Typically, OPcache isn't enabled by default in the CLI, which can give a false impression of performance if you're only testing there. To make use of OPcache in CLI, you'll need to turn it on explicitly in your php.ini file.
On the flip side, Webdock stacks come with OPcache already activated for PHP-FPM. This setup is designed to boost performance when running PHP scripts through a web server. So, if you run the bench.php script in a browser, you can see performance improvements ranging from 30% to 40% compared to running it via CLI.
This speed boost comes from OPcache's ability to cache compiled script bytecode, which reduces the time needed to run PHP scripts by reducing the overhead of parsing and compiling code with each request.
It's best to run the benchmark script through a web server instead of in the CLI for accurate benchmarking that reflects how your application performs under typical usage. PHP Benchmark Script lets you test your server even on a browser. Let’s take a look at how you can do so:
First, you’d need to log in as root:
$ sudo su
And open your website’s root folder:
# cd /var/www/html
Then, download the script to this location:
# wget https://raw.githubusercontent.com/SergiX44/php-benchmark-script/master/bench.php
If you have already downloaded it to the /home/(user) folder, then you can also move the file to the website folder:
# mv /home/(user)/bench.php /var/www/html
Remember to replace (user) with the username of your admin username.
Once you have the file in place, simply visit your website domain followed by /bench.php. This would load for a few seconds before showing you results, so don’t think the action is being unresponsive.
If you want to customize the benchmarking process (like changing the difficulty multiplier), you can modify the script or add parameters to the URL. For example:
https://yourdomain.com/bench.php?multiplier=2
This method gives you a clearer picture of how your application will behave in real-world situations and helps you pinpoint any bottlenecks and opportunities for optimization.
Using OPcache effectively in a web environment can provide valuable insights into your PHP application's performance, enabling you to make informed decisions about optimizations and improvements. When benchmarking, always keep in mind the environment you're working in to ensure your results reflect actual usage conditions.
You can add further benchmarks to the PHP Benchmark Script to obtain more extensive performance metrics. These include benchmarks for:
Random Number Generation:
$ wget https://raw.githubusercontent.com/SergiX44/php-benchmark-script/master/rand.bench.php
The rand.bench.php script measures the time it takes to generate a specified number of random numbers. This can help evaluate the performance of the server's random number generation capabilities, which is useful for applications that rely on randomness, such as gaming or cryptography.
File I/O Operations:
$ wget https://raw.githubusercontent.com/SergiX44/php-benchmark-script/master/io.bench.php
The io.bench.php script performs various file operations, such as creating a file, writing data to it, reading the data back, and deleting the file. This gives insights into the server's file system performance, which is crucial for applications that handle large amounts of data or require frequent file access.
MySQL Performance:
$ wget https://raw.githubusercontent.com/SergiX44/php-benchmark-script/master/mysql.bench.php
The mysql.bench.php script typically runs a series of queries to test how quickly the database can handle them, including insertions, updates, deletions, and selections. This helps identify potential bottlenecks in database performance and can inform optimization strategies for database-driven applications.
Once you download the additional scripts, simply run the bench.php command. Moreover, you can create your own tests by placing a file in the same directory as bench.php. Name the file with the pattern *.bench.php.
This file should return either a closure or an array of closures. Each closure will accept a parameter called $multiplier, which determines the difficulty of the test. A higher $multiplier means a longer test duration, with the default set to 1. It’s important to select a reasonable number of iterations for your test, such as 1000, and then multiply that by the $multiplier you choose.
Running the MySQL Benchmark Script
Before I get into action, there are a few prerequisites you need to know. Firstly, I am running the test on Webdock’s famous LEMP server stack. Also, for benchmarking, your MySQL user should be the ‘admin’ to prevent conflicts. You can find these details easily on Webdock’s dashboard:
Now that’s out of the way, let’s try running the MySQL performance script. You'll need to provide the above-mentioned database credentials to execute MySQL benchmarks using the mysql.bench.php script. The typical command would be:
$ php bench.php --mysql_user=admin --mysql_password=yourpassword --mysql_host=localhost
Replace yourpassword with the actual password for the admin user. This command will carry out various database operations (such as select, insert, update, delete) and measure their performance.
Once you run the MySQL benchmark, you may obtain output similar to this after the regular PHP benchmark results:
-----------------Additional Benchmarks----------------- mysql::ping................................... 0.0001 s mysql::select_version......................... 0.0336 s mysql::select_all............................. 0.1028 s mysql::select_cursor.......................... 0.2919 s mysql::seq_insert............................. 0.8913 s mysql::bulk_insert............................ 0.4699 s mysql::update................................. 1.1086 s mysql::update_with_index...................... 0.2139 s mysql::transaction_insert..................... 1.0088 s mysql::aes_encrypt............................ 0.0400 s mysql::aes_decrypt............................ 0.0389 s mysql::indexes................................ 0.1555 s mysql::delete................................. 0.9489 s -------------------------Extra------------------------- mysql::select_version::q/s....................... 29805 mysql::select_all::q/s............................ 9730 mysql::seq_insert::q/s............................ 1122 mysql::update::q/s................................. 902 mysql::update_with_index::q/s.................... 14232 mysql::transaction_insert::t/s..................... 991 mysql::aes_encrypt::q/s.......................... 25253 mysql::aes_decrypt::q/s.......................... 25866 mysql::delete::q/s................................ 1054 ------------------------------------------------------- Total time.................................... 9.1651 s Peak memory usage............................... 10 MiB
Let’s take a quick look at what each pointer means:
- mysql::ping: Time taken to check the connection to the MySQL server. A quick way to see if the server is responsive.
- mysql::select_version: Time taken to retrieve the version of the MySQL server.
- mysql::select_all: Time taken to select all rows from a table.
- mysql::select_cursor: Time taken to select rows using a cursor, which allows processing results one row at a time.
- mysql::seq_insert: Time taken to perform sequential inserts into a table, one row at a time.
- mysql::bulk_insert: Time taken for inserting multiple rows in a single query, which is generally faster than sequential inserts.
- mysql::update: Time taken to update records in a table.
- mysql::update_with_index: Time taken to update records in a table that has an index, which can affect performance.
- mysql::transaction_insert: Time taken to insert records within a transaction, ensuring ACID properties.
- mysql::aes_encrypt: Time taken to encrypt data using AES encryption.
- mysql::aes_decrypt: Time taken to decrypt data using AES encryption.
- mysql::indexes: Time taken to access or process indexes on the tables.
- mysql::delete: Time taken to delete records from a table.
- mysql::select_version::q/s: This measures the number of queries per second (q/s) required to select the version of the MySQL server. A higher value indicates better performance in retrieving server information.
- mysql::select_all::q/s: This indicates the queries per second for selecting all records from a database table. It reflects the efficiency of reading data from the database.
- mysql::seq_insert::q/s: This shows the number of sequential insert operations per second. It evaluates how quickly the database can handle inserting new records.
- mysql::update::q/s: This represents the queries per second for updating existing records in the database. A higher number suggests better performance in modifying data.
- mysql::delete::q/s: This measures the queries per second for deleting records from a database table. It indicates how efficiently the database can remove data.
Understanding Filesystem Settings' Impact on Performance
When benchmarking database performance, it's vital to consider how your server's filesystem settings influence results. For instance, Webdock’s infrastructure has a setting for direct I/O writes called sync=standard; all direct writes are flushed to disk immediately. This setting ensures data safety but can significantly affect performance.
With sync=standard
Let’s take a look at the implications of using sync=standard versus a more lenient setting. Here’s an example of how these settings might influence MySQL performance from a recent MySQL benchmark we took of a server:
-------------------------Extra------------------------- mysql::select_version::q/s........................... 30431 mysql::select_all::q/s............................... 13763 mysql::seq_insert::q/s............................... 262 mysql::update::q/s.................................. 274 mysql::delete::q/s.................................. 248 ------------------------------------------------------- Total time............................................ 18.3358 s Peak memory usage.................................... 12 MiB
Without sync=standard
-------------------------Extra------------------------- mysql::select_version::q/s........................... 28583 mysql::select_all::q/s............................... 7849 mysql::seq_insert::q/s............................... 3894 mysql::update::q/s.................................. 3472 mysql::delete::q/s.................................. 4215 ------------------------------------------------------- Total time............................................ 3.9725 s Peak memory usage.................................... 12 MiB
As illustrated above, disabling direct I/O synchronization can substantially improve insert speeds and overall query performance.
But why does Webdock enable sync=standard by default? There are several reasons, including, but not limited to:
- Data Integrity: By enabling sync=standard, you ensure that all data written to the disk is properly flushed and stored before any confirmation is sent back to the application. This reduces the risk of data loss in case of a system crash or power failure, as only committed transactions will be lost, rather than potentially corrupt or incomplete data.
- Improved Performance: While it may seem counterintuitive, using sync=standard can enhance performance for certain workloads. By batching write operations, the server can optimize how data is written, reducing the number of individual disk writes. This can lead to more efficient use of disk I/O resources, especially under heavy load.
- Consistency Across Restarts: With sync=standard enabled, you can achieve higher consistency when your server restarts. The data that was acknowledged as written before a restart will be intact, allowing for a more reliable recovery process. This is particularly important for applications that require a high level of consistency, such as databases or transaction-based systems.
- Easier Troubleshooting: With sync=standard, you can simplify troubleshooting and diagnostics. Since data is written in a consistent manner, it becomes easier to trace issues related to data integrity and application behavior. If problems arise, you can be more confident that the data you are examining is complete and accurately reflects the state of your application at the time of the write operation.
If your application is write-heavy — indicating it performs numerous database insertions — you may want to contact Webdock support to discuss disabling direct I/O synchronization with the underlying filesystem.
Note: While this change can potentially enhance performance (often by 4-5 times), it comes with associated risks of data loss in case your server crashes or if there’s a power outage in the data center. To mitigate this, you may want to have a robust backup strategy ready if you implement this change.
Tips Before Taking Action
Before making any alterations to your server to improve performance based on benchmarking results, I would recommend conducting thorough testing in a controlled yet similar environment. This enables you to evaluate how changes might impact both performance and stability without affecting production systems.
In Conclusion
Benchmarking is an essential component of maintaining and optimizing your PHP applications. Using the PHP Benchmark Script provides valuable insights into your application's performance under varying conditions.
Adding additional benchmarks for file I/O and MySQL operations gives you a holistic view of your application’s performance.
Moreover, understanding how filesystem settings like sync=standard affect database operations is crucial for making informed decisions regarding server configurations. If you manage a write-heavy application, consider contacting Webdock support to explore options for enhancing database insert performance.
Incorporating these practices will help ensure that your PHP applications operate efficiently on your web server, providing an enhanced user experience and maximizing resource utilization. Happy Benchmarking!
Meet Aayush, a WordPress website designer with almost a decade of experience who crafts visually appealing websites and has a knack for writing engaging technology blogs. In his spare time, he enjoys illuminating the minds around him.
Related articles
-
Optimizing Network Speed on Your Webdock KVM Server
A mini article with some kernel tweaks to improve network performance on your server
Last updated: September 6th 2024
-
How to configure Crontab on Linux
In this article we detail how Crontab works and all the available options for configuration along with correct syntax and examples.
Last updated: January 4th 2024
-
How to free up disk space on an Ubuntu Nginx or Apache Web Server
This article outlines useful commands you can run on your server in order to free up disk space.
Last updated: October 16th 2023
-
How to monitor webdock server resources using Prometheus, Grafana, Node Exporter and Prometheus Alert Manager
This guide includes the step by step procedure of installing different packages like Prometheus, Grafana, Node exporter and Alert Manager.
Last updated: December 7th 2022
-
How to Disable IPv6 on Your Webdock Server
The article explain how to disable IPv6 on your Webdock server, both temporarily and permanently.
Last updated: August 13th 2024
-
Automating Initial Server Configuration with Ansible
Read our new article: Learn how to automate your cloud server configuration using Ansible.
Last updated: July 19th 2023
-
Top Tools to Install on Your Ubuntu Web Server
A list of important tools that you can install on your production Ubuntu web server
Last updated: July 19th 2023
-
How To Benchmark Your Server with YABS
A guide to do benchmarking of your server's CPU, network performance, and such using YABS.
Last updated: April 1st 2024
-
Systemd Units - A Comprehensive Guide for Linux Admins
A detailed guide on systemd internals for Linux admins
Last updated: August 13th 2024
-
A Quick Guide to Managing Systemd Services
A short guide that helps you manage systemd services
Last updated: August 13th 2024
-
Why don't I have the memory or disk allowance that I expect?
In this article we show why inside your instance you may see lower than expected RAM or DISK allowance available. It has all to do with units!
Last updated: November 29th 2024