Is PHP Compiled or Interpreted? The Complete Answer
PHP has come a very long way from its origins as a simple templating tool. Today, its impressive performance is the result of a sophisticated, multi-layered execution model. So, when someone asks if PHP is compiled or interpreted, the most accurate answer is: it’s both. It uses a hybrid model that combines the best of both worlds.
Let's break down exactly what happens when a PHP script is executed.
A Simple Analogy: The Coffee Shop ☕
Imagine you're ordering a coffee. This simple process is a great analogy for how PHP works.
-
Your Order (The PHP Script): You ask for a "large latte with oat milk". This is your high-level, human-readable instruction.
-
The Barista (The PHP Compiler): The barista takes your order and, instead of keeping the long phrase in their head, writes a highly efficient shorthand on the cup: L-OAT-L. This translation from your request to their internal language is the compilation to Opcodes. It’s a one-time conversion of your code into something the machine can understand much faster.
-
Making the Coffee (The Zend VM): The barista then follows the L-OAT-L instructions—grind beans, pull shot, steam milk, combine. This action of reading the shorthand and performing the task is the interpretation step, carried out by the Zend Virtual Machine.
-
The Smart Till (OPcache): Now, imagine the coffee shop's till is smart. After the first order, it saves that Large latte with oat milk translates to L-OAT-L. The next time someone places the exact same order, the barista doesn't need to translate it again; the till provides the shorthand instantly. This is OPcache. It stores the compiled Opcodes in memory, so for the next request, PHP can completely skip the compilation step and go straight to execution. This is the single biggest performance boost for most PHP applications.
-
The "Special" Button (JIT Compiler): The barista notices they're making dozens of L-OAT-Ls an hour. To optimise this "hot path," they program a special button on the coffee machine that does the entire sequence automatically. This is the Just-In-Time (JIT) Compiler. It takes extremely common sets of Opcodes and compiles them all the way down to native machine code, making those specific tasks run even faster.
The Technical Breakdown
The coffee shop analogy directly maps to the technical steps:
Compilation to Opcodes: Your PHP script is parsed and compiled into a set of low-level instructions (Zend Opcodes) that are easy for a machine to understand.
Execution by the Zend VM: The Zend VM (the heart of PHP) takes these Opcodes and executes them, running your application's logic.
The Performance Layers: OPcache and JIT Without caching, the compilation step would happen on every single request, which is inefficient. Modern PHP solves this with two powerful layers of optimisation.
OPcache (The First Layer of Speed): As the analogy showed, OPcache stores the compiled Opcodes in shared memory after the first run. This means for subsequent requests, PHP skips the expensive compilation work entirely. In a production environment, this is not optional; it's a fundamental requirement for a high-performance application.
JIT (The Next Gear): Introduced in PHP 8, the JIT compiler is the next layer. It watches for frequently executed sequences of Opcodes (hot code) and compiles them into highly optimised machine code that can be run directly by the CPU. While OPcache speeds up all code, JIT provides the biggest gains for CPU-intensive tasks, like complex calculations or data processing, rather than typical web requests, which often wait for the database or network.
What This Means for Us as Developers
Understanding this process is key to writing better applications.
Trust the Engine: We can write clean, readable, high-level PHP code, confident that the Zend Engine is doing a tremendous amount of low-level optimisation for us.
Server Configuration is Crucial: Your application's performance is directly tied to your server setup. Ensuring OPcache is enabled and properly configured is the most important takeaway.
The Best of Both Worlds
We get the rapid development and flexibility of an interpreted language with performance that, thanks to these layers of compilation and caching, approaches that of traditionally compiled languages.
Configuring OPcache for Production Performance
Understanding OPcache is one thing, but configuring it correctly is what unlocks its full potential. These settings are managed in your server's 'php.ini' file. After making any changes, you'll need to restart your web server or PHP-FPM service.
While there are many directives, a few are critical for a high-performance production environment.
Here's a recommended baseline configuration: Ini, TOML
; The master switch. Must be set to 1 to enable OPcache. opcache.enable=1 ; The amount of memory to allocate for opcodes, in megabytes. ; For a medium-sized application, 128MB is a good starting point. opcache.memory_consumption=128 ; The amount of memory for storing identical strings, in megabytes. ; This helps reduce memory usage. 16MB is a sensible default. opcache.interned_strings_buffer=16 ; The most important performance setting for production. ; When set to 0, PHP will NOT check if your files have changed. ; This gives maximum performance but means you must manually clear ; the OPcache after every deployment. opcache.validate_timestamps=0 ; How many files can be cached. Set this higher than the number ; of PHP files in your project. opcache.max_accelerated_files=10000
The most critical setting here is
opcache.validate_timestamps
. In a development environment, you'd set this to 1 so OPcache checks for file changes on every request. In production, setting it to 0 provides a significant speed boost because the server never spends time checking for updates. The trade-off is that you must have a deployment process that clears the OPcache (e.g., by restarting PHP-FPM) to make your new code live.