No reasonable WordPress site is complete without some kind of caching plugin. While PeachPie should inherently speed up the runtime of PHP apps, it also opens up the door to another fantastic possibility: the ASP.NET Core response cache.
The web cache is a general issue we will face regardless of language, web server or platform. In the PHP environment specifically, virtually any framework or CMS includes their own implementation or provides a tutorial on how to configure the cache. In this article, we suggest a rather amazing alternative.
PeachPie is a compiler and runtime of the PHP language under .NET and .NET Core. By compiling PHP to CIL bytecode, PeachPie bridges the gap between these two technologies and essentially allows developers to take advantage of to the rich PHP ecosystem combined with the many fantastic tools the .NET world has to offer. One of these tools is the powerful ASP.NET Core response caching middleware, which is what we’ll focus on in this article.
Why the ASP.NET Core response cache?
With PeachPie, we find ourselves in the .NET Core environment; a PHP site is compiled and runs as a native .NET application, which allows us to combine the solution with the .NET platform. Moreover, the ASP.NET Core response cache sits directly on the pipeline of the ultimate lightweight web server, which is known to produce blazing fast speeds. This cache is fully configurable thanks to a dependency injection and highly performant. And finally, the cache mechanism is compiled, which means that in the case of a ‘cache hit’, not a single line of PHP code is executed.
Example for the curious ones
If you already know enough, feel free to skip right to the results; here is a link to a GitHub project that compiles all of WordPress and handles the requests in your ASP.NET Core app using this compiled version of WordPress.
Take note of:
Thanks to the combination of PeachPie and ASP.NET Core, this will switch on the server-side in-memory response cache in your PHP web.
WordPress and app-specific behavior
Each application has its specific behavior and the cache needs to be refreshed intelligently. The standard Response Cache setting goes by the response headers configured by the website’s code; if the PHP code correctly sets the expiration and similar parameters and there is no need to explicitly delete the cache, everything will work out of the box.
Applications such as WordPress, however, don’t do this and even more so, the cache needs to be dumped when, for example, a comment is added to an article or a blog post was edited. It is also not advisable to cache anything (or only some sites) for a logged in user, seeing as some of the content will be specific to that user. This can be achieved by implementing one’s own
IResponseCachingPolicyProvider, as seen here:
The instance of this object is injected into the
ResponseCachingMiddleware construct. The object defines the cache’s behavior – whether to save a specific Http Request and whether to subsequently store the Http Response in the cache. In our case, the interconnection with PHP is more interesting, however.
Our goal is to subsequently call our
IResponseCachingPolicyProvider and tell it to dump the cache. In the case of WordPress, we designed and implemented a C# add-on that defines the
IWpPlugin interface, among others. This enables us to add so called hooks during each request to WordPress and thus connect to the ‘callback’ API of WordPress. This procedure will be very similar regardless of which PHP project we are using.
Using WordPress as an example, we are adding an event handler into the WordPress filter “save_post”, as seen here:
WordPress will then call us when this event will be triggered and we can thus store the current time. All following requests to the cache merely return the cached content created before this time.
The main advantage of this new mechanism rests in its simplicity and versatility. Our solution is identical and universal across any PHP website without having to change the PHP code or modify its logic. Nevertheless, measuring PHP code in this particular area makes little to no sense. No PHP code is being executed and the benchmarks are thus identical with the aforementioned TechEmpower benchmarks.
The process is as follows: a request reaches the server – the ResponseCache sits first in the request pipeline – it finds the cached content and instantly returns it – end of request. However, in the future we are planning on preparing a comparison with the popular WP-Super-Cache plugin, which our built-in ASP.NET Core response cache renders obsolete (when running WordPress on .NET). This plugin has several modes – the one that can be compared with ours in terms of speed, however, requires a modification of the Apache configuration file; thanks to this, Apache routes the request directly to the cached file on the disk.
All in all, thanks to the ASP.NET Core Response Cache, we can serve a majority of WordPress requests with a minimal effort in about 4 ms.
You can find our WordPress SDK to study and analyze here.