Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Conferences
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
High Performance with Laravel Octane

You're reading from   High Performance with Laravel Octane Learn to fine-tune and optimize PHP and Laravel apps using Octane and an asynchronous approach

Arrow left icon
Product type Paperback
Published in Jan 2023
Publisher Packt
ISBN-13 9781801819404
Length 204 pages
Edition 1st Edition
Languages
Tools
Arrow right icon
Author (1):
Arrow left icon
Roberto Butti Roberto Butti
Author Profile Icon Roberto Butti
Roberto Butti
Arrow right icon
View More author details
Toc

Table of Contents (14) Chapters Close

Preface 1. Part 1: The Architecture
2. Chapter 1: Understanding the Laravel Web Application Architecture FREE CHAPTER 3. Part 2: The Application Server
4. Chapter 2: Configuring the RoadRunner Application Server 5. Chapter 3: Configuring the Swoole Application Server 6. Part 3: Laravel Octane – a Complete Tour
7. Chapter 4: Building a Laravel Octane Application 8. Chapter 5: Reducing Latency and Managing Data with an Asynchronous Approach 9. Part 4: Speeding Up
10. Chapter 6: Using Queues to Apply the Asynchronous Approach in Your Application 11. Chapter 7: Configuring the Laravel Octane Application for the Production Environment 12. Index 13. Other Books You May Enjoy

Understanding performance measurement in Laravel Octane

We have said that introducing Laravel Octane in your application allows for a performance boost, mainly because the objects and the various instances of the classes used by the framework are no longer initialized at every single HTTP request but at the start of the application server. As a result, for each HTTP request, framework objects are reused. Reusing framework objects saves time in serving the HTTP request.

While, on a logical and understandable level, this can have a positive impact in terms of performance, the goal of this part is to get pragmatic feedback on this performance boost by trying to recover some metrics and values.

In order to provide a rough indication of the benefits and improved response time performance for a request, let us try to perform a simple performance test.

To do this, we are going to install a tool to generate and execute some HTTP-concurrent requests. There are several such tools, one of which is wrk (https://github.com/wg/wrk).

If you have a macOS environment, you could use the brew command (provided by Homebrew) to install the wrk tool. To install the tool, use brew install as shown:

brew install wrk

With wrk, you can generate concurrent requests for a defined amount of time.

We will conduct two tests for comparison: one test will be conducted with a classical web application on nginx (http://octane.test), and the other one with an application served by an application server on Laravel Octane (http://octane.test:8000).

The two URLs are resolved as shown:

  • http://octane.test/ is resolved with local address 127.0.0.1 and will reply nginx
  • http://octane.test:8000/ is resolved with local address 127.0.0.1 and port 8000 is bound by Swoole

The wrk execution will use 4 threads, open 20 connections, and take 10 seconds of tests.

So, to test NGINX, launch the wrk command with these arguments:

wrk -t4 -c20 -d10s http://octane.test

You will see the following output:

Running 10s test @ http://octane.test
  4 threads and 20 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    51.78ms   61.33ms 473.05ms   88.54%
    Req/Sec   141.79     68.87   313.00     66.50%
  5612 requests in 10.05s, 8.47MB read
  Non-2xx or 3xx responses: 2
Requests/sec:    558.17
Transfer/sec:    863.14KB

To test Laravel Octane (RoadRunner), use the following command:

wrk -t4 -c20 -d10s http://octane.test:8000

You will see the following output:

Running 10s test @ http://octane.test:8000
  4 threads and 20 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency   134.58ms  178.24ms   1.09s    79.75%
    Req/Sec   222.72    192.63     1.02k    73.72%
  7196 requests in 10.02s, 8.06MB read
Requests/sec:    718.51
Transfer/sec:    823.76KB

This test is very basic because there are no special server-side logic or query databases involved, but it is good to run the test to understand the raw difference in bootstrapping basic objects for Laravel (application container, requests, etc.) and perceive their flavor.

The difference is not so great (7,196 requests versus 5,612 requests) – around 22% – but consider that this difference grows if you add new packages and libraries (more code to be bootstrapped for each request).

Consider also that RoadRunner and Swoole provide other additional tools for improving performances such as enabling concurrency and executing concurrent tasks. The additional tools will be shown later in Chapters 2 and 3.

To better explain why Laravel Octane allows you to achieve this improvement, let me demonstrate how and when service providers are instanced and loaded into a service container.

Typically, in a classic Laravel application service, providers are loaded in each request.

Create a new service provider named MyServiceProvider in the app/Providers directory:

<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class MyServiceProvider extends ServiceProvider
{
    public function __construct($app)
    {
        echo "NEW     - " . __METHOD__ . PHP_EOL;
        parent::__construct($app);
    }
    public function register()
    {
        echo "REGISTER     - " . __METHOD__ . PHP_EOL;
    }
    public function boot()
    {
        echo "BOOT     - " . __METHOD__ . PHP_EOL;
    }
}

The new service provider simply shows a message when the service provider is created, registered, and booted.

The lifecycle of a service provider starts with three phases: creation, registration, and boot.

The register() and boot() methods are needed for dependency resolution. First of all, every service provider is registered. Once they are all registered, they could be booted. If a service provider needs another service in the boot method, you can be sure that it is ready to be used because it is already registered.

Then, you have to register the service provider, so in config/app.php in the providers array, add App\Providers\MyServiceProvider::class.

In a classical Laravel web application, for every HTTP request, the MyServiceProvider service provider is instanced, and the construct, register, and boot methods are called every time, showing this output:

NEW          - App\Providers\MyServiceProvider::__construct
REGISTER     - App\Providers\MyServiceProvider::register
BOOT         - App\Providers\MyServiceProvider::boot

With Laravel Octane, something different happens.

For a better understanding, we are going to launch the Laravel Octane server with two parameters:

  • workers: The number of workers that should be available to handle requests. We are going to set this number to 2.
  • max-requests: The number of requests to process before reloading the server. We are going to set this number to a maximum limit of 5 for each worker.

To start the Octane server with two workers and reload the server after processing five requests, we enter the following command:

php artisan octane:start --workers=2 --max-requests=5

After launching Octane, try to perform more than one request with the browser accessing this URL: http://127.0.0.1:8000.

The following is the output:

NEW          - App\Providers\MyServiceProvider::__construct
REGISTER     - App\Providers\MyServiceProvider::register
BOOT         - App\Providers\MyServiceProvider::boot
  200    GET / ...................................................... 113.62 ms
NEW          - App\Providers\MyServiceProvider::__construct
REGISTER     - App\Providers\MyServiceProvider::register
BOOT         - App\Providers\MyServiceProvider::boot
  200    GET / ....................................................... 85.49 ms
  200    GET / ........................................................ 7.57 ms
  200    GET / ........................................................ 6.96 ms
  200    GET / ........................................................ 6.40 ms
  200    GET / ........................................................ 7.27 ms
  200    GET / ........................................................ 3.97 ms
  200    GET / ........................................................ 5.17 ms
  200    GET / ........................................................ 8.41 ms
worker stopped
  200    GET / ........................................................ 4.84 ms
worker stopped

The first 2 requests take around 100 milliseconds (ms), the next requests take 10 ms, and the register() and boot() methods are called on the first two requests.

So we can see the first two requests (two because we have two workers) are a bit slower (113.62 ms and 85.49 ms) than the next requests (from the third to the tenth request, where we have a response time of less than 10 ms).

Another important thing to mention is that the register and boot methods are called for the first two requests until the tenth request (two workers multiplied by five max requests). This behavior is repeated for subsequent requests.

And so, installing Laravel Octane in your web application allows you to improve the response time of your application.

All this without having involved certain tools such as concurrency management provided by application servers such as Swoole and RoadRunner.

You have been reading a chapter from
High Performance with Laravel Octane
Published in: Jan 2023
Publisher: Packt
ISBN-13: 9781801819404
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $19.99/month. Cancel anytime
Banner background image