در حال بارگذاری ...

PHP Request Lifecycle Overhead0:28

It could be a VBS in the cloud or an on-premise server. This server has a web server installed, let's say, Nginx. Nginx receives a request, routes it to php for processing, takes the response, and sends it back to the client. Let's take a look at a poorly performing php application and how it would look like. When this application receives a request, it starts a new process. And starting a new process is a relatively expensive task, as the operating system needs to allocate a memory space that is isolated from other processes.

as the operating system needs to allocate a memory space that is isolated from other processes. By expensive, I mean that it takes a lot of CPU time. Next, the php process loads the index.php file from Dusk, and then it interprets it. A CPU doesn't know how to execute PHP scripts. It doesn't speak PHP. So PHP programs rely on the Zend engine to translate PHP scripts into OB codes, and then later translate this OB code to machine code,

to translate php scripts into OB codes, and then later translate this OB code to machine code, which the CPU understands. Translating php scripts into OB codes is an expensive task. It requires a lot of CPU time. Now that the index.php file is loaded and translated, php loads and translates all other php files that are included or required in your project. That means all framework files, all package files, and all your application files in general.

That means all framework files, all package files, and all your application files in general. Loading and interpreting all those files is super expensive. Moving on, once the php program is translated into OPcodes, the Zend engine starts executing the OPcodes. In other words, your Laravel application gets bootstrapped and loaded into the process memory. All the objects, all the static variables, and all the global variables, they all get initialized and loaded into memory,

The php process is terminated. So let's visualize this. For every request, a process starts, files are loaded, PHP code is translated, executed, and then the process is shut down. As we mentioned, all these tasks are quite expensive. Starting processes is expensive, interpreting PHP scripts is expensive, and terminating processes is also expensive. All these tasks add to the time it takes

Reducing Processes with PHP-FPM4:10

That's what people normally mean when they say a certain stack cannot scale. They mean it will be expensive to run this stack when the traffic increases. Let's go check what the php community has done to increase the efficiency of running PHP web applications and make it more scalable. To avoid having to start a process for each and every single request, PHP FPM maintains a pool of processes.

This, of course, reduces the overhead of starting and terminating processes for each and every single request. Now, inside the request handler, php FPM creates a context, loads the file, interprets the scripts, executes the OB codes inside the context, and generates a response. This context is a unique state that describes the current request this process is handling.

that describes the current request this process is handling. It lives in the process memory and contains all the application objects, static variables, and global variables as well. Now, when a new request comes in, a fresh context is created for it. Using php-fpm, we eliminate the overhead of creating processes, but we still have other expensive tasks.

Caching Opcodes with OPCache5:48

of creating processes, but we still have other expensive tasks happening for every request, mainly creating contexts and interpreting PHP scripts. And to deal with the latter, the opcache PHP extension was introduced. It allows us to cache the interpreted OP codes and reuse them in future requests. That means we will only pay for the price of interpretation once

That means we will only pay for the price of interpretation once and use it for free later. Use the OB code, I mean. While handling a request, PHP FPM will check if a script was interpreted before and reused its OB code. But if not, it will interpret the code and store it in the OB cache. The cached OB code is shared.

and store it in the OB cache. The cached OB code is shared between all php-fpm processes, so only the first request in any worker has to interpret the script. Future requests in any worker, not the same worker, not necessarily the same worker, just reuses the cached OB code. That makes request handling look like this when OB code is cached.

That makes request handling look like this when OB code is cached. Mainly creating the context, loading files, executing code, and terminating the context. And to optimize this further, we need to eliminate having to create a context and loading files for every single request. And to go even further, we need to compile the OB code to machine code.

Considering JIT Compilation7:18

And to go even further, we need to compile the OB code to machine code and execute it directly, instead of having the Zend engine translate it to machine code first and then execute it. And that's how Go or Rust programs run. The code is compiled to machine code and is executed directly. In PHP, the compilation happens by the Zend engine at runtime.

In PHP, the compilation happens by the Zend engine at runtime. In Go and Rust, the compilation happens at build time. In PHP 8, however, a just-in-time compiler was introduced. It still compiles the code at runtime, but it caches the machine code and reuses it directly in the future. As great as this sounds, I haven't personally seen any production-grade applications use it and present positive results,

Introducing Laravel Octane8:05

I haven't personally seen any production-grade applications use it and present positive results, so I will not get into the JET compiler in this course. Instead, we will look into the other optimization possibility, which is not having to create a context for each and every single request. The possibility of loading the Laravel application once, keeping it in memory, and using the same instance to process all incoming requests. That's what Laravel Octane offers.

and using the same instance to process all incoming requests. That's what Laravel Octane offers. Taylor Otwell created Octane so that Laravel applications that experience high traffic can handle more requests without having to pay for more expensive servers. Fasten your seatbelts and join me in exploring Laravel Octane. I will see you in the next lesson.

OPCachePHP-FPM

دوست دارید گاهی خبرهای Laracasts را ایمیل کنیم؟