About Preloading in PHP
PHP is on an upward trajectory — the more recent improvements to the language are a testament to this postulate. Preloading — a feature inspired by the Java Hotspot Virtual Machine — is yet another enhancement to the PHP runtime. Initiated as an RFC by Dmitry Stogov, preloading presents an upgrade to the Zend OPCache responsible for caching opcodes generated upon PHP code compilation.
The quintessence of preloading is storing PHP code in the OPCache thereby availing it to all dependent scripts as part of the language core. To understand the concept of preloading, a revision of the PHP lifecycle and PHP code execution phases is apt.
PHP code executes in four stages: lexing, parsing, compiling and interpreting. PHP code execution starts with a lexer which converts executable PHP to parsable tokens. The process continues with the parser which analyzes PHP tokens and forms Abstract Syntax Trees (ASTs) in a top-down, left-to-right manner. The compilation phase is interesting: ASTs are, at this point, converted to Opcodes. The OPCache exists at this level and serves to preempt redundant compilation of frequently used PHP sequences. Interpretation by the PHP Virtual Machine is the natural culmination of the process. PHP’s progenitor is the C programming language: it actualizes PHP’s operational semantics. I suggest that you, the reader, watch the video titled Climbing the PHP Abstract Syntax Tree if you intend to understand some of the more arcane workings of the PHP virtual machine.
Onto the PHP lifecycle and end of this short reappraisal — PHP has a four-step run cycle for both threaded and non-threaded runtimes. Because PHP is almost entirely server-dependent (one of either Apache or NGINX should suffice), the first stage in the language’s lifecycle is initiation as a server module — a process dubbed MINIT. It is, therefore, safe to posit that as soon as a web-server configured to run PHP starts, a compatible PHP runtime starts as well. PHP then enters the Request Startup phase aliased RINIT upon receiving computation load — requests. The language runtime momentarily shuts down request handlers initiated by RINIT soon after discretely processing output and prepares itself to handle new ones — this stage in the cycle is RSHUTDOWN. Finality in the language lifecycle materializes at Module Shutdown, MSHUTDOWN. PHP shuts down after serving multiple requests.
How are the concepts in the antecedent text linked with Preloading? PHP source code receives a compilation boost from preloading which is — according to the RFC — capable of allowing partial or complete pre-optimization of entire libraries and frameworks by loading said utilities into the OPCache at the Module Startup (MINIT) phase. As such, a server restart is a prerequisite for any OPCache preload modifications — additions and omissions from the preload suite. If you frequently use shared-hosting solutions, you might not enjoy the full potencies of the optimization.
There exists a snippet of code from the original RFC which provides a meaningful insight into preloading. Also, a Composer plugin created by Ajesh Karunaratne specifically for preloading shows how the bootstrapping capabilities of said dependency manager are combinable with the robustness of preloading. Recently merged into one of PHP’s codelines, preloading is set to feature in the PHP universe in version 7.4.
Preloading is no substitute for a Just-In-Time (JIT) compiler which is a lot more powerful and complicated. It is, however, a great way to optimize PHP code. I remain grateful for the contributions of individuals like Mr. Stogov and the maintainers of the PHP language core who continue to improve the language. I advise that you, the reader of this article, continue to pay heed to the improvements in the PHP environment and show support by writing great PHP code.