PHP 5.5 introduced opcode caching into the core via OPCache. OPCache was previously known as Zend Optimizer+, and although free, was closed source. Zend decided to open source the implementation, and include it in the core PHP distribution. OPCache is also available as an extension through pecl, and is compatible all the way back to PHP 5.2. While other opcode caching solutions like APC exist, now that OPCache is bundled with PHP, it will likely become the standard going forward.

What is an opcode cache, and how does it work? Every time a PHP script is requested, the PHP script will be parsed and compiled into opcode which then is executed in the Zend Engine. This is what allows PHP developers to skip the compilation step required in other languages like Java or C# — you can make changes to your PHP code and see those changes immediately. However, the parsing and compiling steps increase your response time, and in a non-development environment are often unnecessary, since your application code changes infrequently.

When an opcode cache is introduced, after a PHP script is interpreted and turned into opcode, it’s saved in shared memory, and subsequent requests will skip the parsing and compilation phases and leverage the opcode stored in memory, reducing the execution time of PHP.

How much benefit can you expect from an opcode cache? Like many things in life, the answer is it depends. To test the benefit of OPCache, we have taken an existing PHP demo application used at AppDynamics, and installed OPCache. The OPCache settings were fairly straightforward, but we opted to use 0 for the refresh rate, which means a script will never be checked to see if it’s updated. While applicable for a production environment, it means you must delete the opcache cache when deploying new code.

The demo application is a simple e-commerce site built on top of Symfony 2 and PHP 5.4, leveraging a MySQL database, memcache and a backend Java service. For the test, the demo application is running on a medium ec2 instance (database, memcached, and Java services are on separate instances) with a small but steady amount of load on four different pages within the application.

In order to understand the performance benefit of enabling OPCache, the AppDynamics PHP agent was installed. The PHP agent auto-discovers application topology, and tracks metrics and flow maps for business transactions, app services, and backends in your web application by injecting instrumentation in the PHP-enabled web server instance at runtime. By leveraging the metrics collected by AppDynamics, we can see the decrease in response time OPCache provides.

Once OPCache was enabled on the application, there was a 14% reduction in response time for the application overall. AppDynamics has a feature called “compare releases” which allows you to select to separate time ranges and compare key metrics. In the screenshot below, we are comparing two small time ranges – March 14th from 9:00am to 12:00pm and March 14th from 1:00pm to 4:00pm, as OPCache was enabled at 12:10pm on March 14th.

While a 14% decrease in response time is good, especially considering the minimal amount of work required to install and enable OPCache, it may be less than you were expecting. The overall application decrease in response time obscures the variation seen across different pages within the application.

AppDynamics analyzes a concept called a business transaction, which represents an aggregation of similar user requests to accomplish a logical user activity. In this demo application, we were generating load on four specific business transactions: View Product, Search, Login, and Loop. Using the compare releases functionality from AppDynamics, instead of focusing on the individual business transactions, we see a lot of variation between the different business transactions in response time once OPCache was introduced.

Let’s look at each business transaction and determine why some transactions saw a large reduction in response time, while others experience a moderate or minimal decrease in response time.

The login business transaction saw a substantial decrease in response time, 74%.

The Login business transaction is relatively simple, as shown by the AppDynamics flow map below (a flow map graphically represents the tiers, nodes, and backends and the process flows between them in a managed application). The transaction goes through a standard Symfony controller and renders a basic html form to login — there are no databases or external services involved. On this particular business transaction, a majority of the response time was spent parsing and compiling the PHP. Once those steps are removed via an OPCache, the response time drops dramatically.

The Product View business transaction experience a similar decrease in response time at 74%.

The Product View business transaction relies on both memcache and MySQL database, although only 2% of the request time is spent outside of PHP (after OPCache was turned on, this increased to 8%), and hence we see a large benefit from opcode caching like we saw in the Login business transaction.

The Search business transaction response time dropped by only 8%.

Looking at the flow map, the majority of the response time is spent on the Java backend service, with a small amount of time spent in the network. Enabling OPCode resulted in a 70% reduction in response time in PHP, but since PHP was only 11% of the overall response time, the effect was muted.

Before:After:

The Loop business transaction is not part of the demo application, but was added specifically for this test. The Loop business transaction saw only a 6% decrease in time.

Loop is 3 lines of code – it loops 10 millions times and increments a counter on each loop. The amount of time it takes to parse and compile the code is small compared with the time it takes to actually execute the opcode, hence the small decrease in response time form enabling opcode caching.

To illustrate the difference we can review a call graph of each transaction. AppDynamics captures snapshots of certain requests, and a snapshot contains the call graph. Looking at the call graphs below for Loop and Login, we see Login has a lot more PHP code to parse and compile:

Loop

Login

In summary, opcode caches provide a quick way to decrease the latency of your PHP application and should always be enabled in production PHP environments. The decrease in response time will primarily depend on two things: 1. The amount of time the request spends in PHP. If your application spends a lot of time waiting for a database to return results or relies on slow third party web services, the decrease in response time from an opcode cache will be on the lower side. 2. If your PHP scripts are very basic, including only the minimal amount of code to process the request, as compared to using a framework, then the reduction in response time will also be limited. Get started by upgrading to PHP 5.5 or installing Zend OpCache today.

Take five minutes to get complete visibility and control into the performance of your production applications with AppDynamics Pro today.

In my previous post I installed and configured Ghost (a node.js based blogging platform) and WordPress (a PHP based blogging platform and CMS). The purpose of that blog postwas to test relative performance of the 2 platforms to see which one could handle more load. The test doesn’t compare like code between node.js and PHP, but instead was designed to understand what platform was faster from a basic blog functionality standpoint.

The result of the first set of tests was that Ghost was 678% faster than WordPress in their “out of the box” configurations. The test and results spurred a lot of interesting dialogue with many people requesting another test where an opcode cache was in place for WordPress. So that is exactly what this next blog post is about.

The Setup

I fired up the exact servers that I had used in my last round of testing so I have the same configuration as in my original blog post. For this set of tests I stuck with Apache as the web server for both Ghost and WordPress. I also added APC opcode cache by following the instructions in this blog post. It was pretty easy and painless getting APC installed and functional and it definitely made a nice difference in the performance of WordPress.

The Results

As before, I used Siege to apply load to the platforms. As a reminder of our WordPress baseline I ran a load test on Apache + WordPress first without the APC opcode cache. Those results are shown below.

Apache+Wordpress under heavy load.

CPU utilization during Apache + WordPress load test.

This load test resulted in 100% CPU utilization just as we had seen in my last blog post. I load tested Apache + Ghost again so that we could compare the base configurations and those results are shown below.

Apache + Ghost heavy load test results.

CPU utilization during Apache + Ghost heavy load test.

As expected Ghost had a much higher transactional throughput ~654% more than WordPress. So now came the real fun. Configure PHP to use APC, restart Apache, and restart the load test. Those results are shown below.

Apache + WordPress + APC heavy load test results.

Much better results for WordPress this time with ~159% improvement in throughput over WordPress without an opcode cache. Transaction response times were also much better showing with ~70% reduction in shortest response time and ~63 percent reduction in longest response time. That’s a nice performance gain for a small bit of work installing and configuring APC. I have included a couple of screenshots for those who are curious about key cache metrics (notice the high cache hit rate)…

While the improvement to WordPress was admirable the fact still remains that Ghost handled the load way better than WordPress. The results of this test show Ghost with a ~190% lead over WordPress when it comes to total throughput, ~51% faster for shortest response time, and ~80% faster for the longest response time.

It’s worth mentioning that the CPU load did not decrease while using the opcode cache during this test. Utilization stayed pegged at 100% for the duration of the test even though throughput and responsiveness improved.

What about lighter loading?

It’s also interesting to understand the difference in platform response time under light loading conditions. The following screen shots all show loads of 10 concurrent users in batches that are spaced 5 seconds apart. The combination of Apache and Ghost is just flat out fast and sets the bar for transaction response time with .01 seconds for the fastest transaction and .07 seconds for the slowest transaction.

Apache + Ghost light load test results.

Apache and WordPress without any opcode cache (shown below) is respectably fast coming in at .20 seconds for the fastest transaction and .66 seconds for the slowest. That is 1900% and 842% worse than Ghost respectively. The percentages are high but the reality is that the page loads are still fast.

Apache + WordPress light load test results.

Adding the APC opcode cache to the Apache and WordPress combination clearly makes pages load faster even under light load. You can see below that the fastest transaction took .07 seconds and the slowest took .25 seconds. That’s a very nice improvement in speed. It’s still considerably slower than Ghost response times but at these speeds nobody will notice the difference.

Apache + WordPress + APC light load test results.

Conclusion

One of the major difference between these two platforms is that Ghost was designed to be just a blogging platform so it is not bloated like WordPress is these days. I love the functionality that WordPress offers but as far as plain old blogging platforms go I think Ghost is going to be pretty tough to beat if you need a high throughput platform.

No matter what programming language is used on a project there will always be good code and bad code. By that I mean code that is efficient and effective (good) versus code that is resource heavy and potentially buggy (bad). If your application isn’t performing the way you want it or the way the business needs it to, then you should try installing AppDynamics for free and figure out what the problems are.