Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Lessons learned from handling 300m+ daily API c...

Lessons learned from handling 300m+ daily API calls using Laravel

Lessons learned from handling 300m+ daily API calls using Laravel

Neo Ighodaro

August 25, 2020
Tweet

More Decks by Neo Ighodaro

Other Decks in Technology

Transcript

  1. There are a lot of things you can do to

    improve performance on your own server or application. Like with most things, it depends on your application. Not every thing in this talk will be applicable to you.
  2. 1LANGUAGE It may seem trivial but keeping PHP updated can

    make a lot of difference especially on systems that have to deal with heavy loads. Each new version has typically increased the amount of requests per second and reduced memory usage. KEEP YOUR PHP VERSION UPDATED Source: https://phoronix.com/scan.php?page=news_item&px=PHP-7.4-Early-Benchmarks
  3. 1LANGUAGE OPTIMIZE PHP PROCESSES By default, php-fpm for instance, will

    have a base configuration. of course this configuration will work just fine but when under heavy loads, you might want to tweak them for better performance. Source: https://tideways.com/profiler/blog/an-introduction-to-php-fpm-tuning
  4. Source: https://www.programmersought.com/article/7229142807/ 2 INFRASTRUCTURE When a new request is received

    in PHP here is a simple representation of what happens and how the request is treated. OPCODE CACHING As seen, parsing the code will happen every time, even if the code did not change. If your code does not change too frequently, you can benefit from opcode caching…
  5. Source: https://www.programmersought.com/article/7229142807/ 2 INFRASTRUCTURE …once an opcode caching extension e.g

    OPCache is enabled, it will cache the opcode and ensure subsequent requests do not have to be parsed. Thus resulting in faster performance. OPCODE CACHING
  6. 2 INFRASTRUCTURE 'So I spun up a small DO droplet

    with 1 CPU and 1 GB RAM and ran Apache Benchmark. I requested the default welcome page of Laravel 5.4 and let the benchmark run for 1 minute with 10 concurrent connections:' OPcache disabled: 10.18 requests per second Enabled with default values: 34.52 requests per second Enabled with optimized values: 42.53 requests per second OPCODE CACHING Source: Olav van Schie https://medium.com/appstract/make-your-laravel-app-fly-with-php-opcache-9948db2a5f93
  7. 2 INFRASTRUCTURE Depending on how aggressive your opcache configuration is,

    you might need to clear the cache after every code change. This can be a little annoying so just installing a laravel package can help with this. After installation you can then add the artisan command to your deploy script. https://github.com/appstract/laravel-opcache OPCODE CACHING $ composer require appstract/laravel-opcache $ php artisan opcache:clear
  8. Source: https://www.cloudways.com/blog/varnish-cache/ Varnish cache is a web application accelerator also

    known as caching HTTP reverse proxy. It acts more like a middle man between your client and your web server. 2 INFRASTRUCTURE HTTP LAYER CACHING
  9. Source: https://www.cloudways.com/blog/varnish-cache/ 1st request: GET /stuff → Web Server →

    PHP process → Client (200ms) Subsequent requests: GET /stuff → Varnish Cache Hit → Client (10ms) 2 INFRASTRUCTURE HTTP LAYER CACHING
  10. 2 INFRASTRUCTURE HTTP LAYER CACHING As with opcache earlier, we

    also have to clear the varnish cache whenever the responded changes. Using a Laravel package we can do this programmatically. With the package we can also set rules on which routes get cache and which routes don't get cache https://github.com/spatie/laravel-varnish $ composer require spatie/laravel-varnish $ php artisan varnish:flush
  11. Some other things you can do: 2 INFRASTRUCTURE HONORABLE MENTIONS

    • Database Optimisation – https://www.cloudways.com/blog/mysql-performance-tuning/ • Web Server Optimisation – https://www.nginx.com/blog/tuning-nginx/ • High Read/Write Storage • Load Balancing • More… Unfortunately, there are just too many things to speak about. We move.
  12. 3 FRAMEWORK CACHE ROUTES AND CONFIGURATION FILES Caching the route

    and configuration files needs to be a part of your build process if you have one. This will remove the need for Laravel to attempt to load the configuration every time it is referenced. You will need to clear and cache the files again if you need to make changes.
  13. 3 FRAMEWORK UNDERSTAND ELOQUENT There is a lot of stuff

    that happens under the hood with Eloquent and understanding some of it will help you understand when using Eloquent can be tricky. !// ~500,000 models in total $cars = Car!::with(‘dealerships’)!->where(‘name’, ‘Benz’)!->get(); This could already lead to high memory usage as Eloquent will create a new model object for each of these rows. You can improve the memory footprint using LazyCollections.
  14. 3 FRAMEWORK UNDERSTAND ELOQUENT When you let’s say loop through

    the entries… For every property we access in this loop, Eloquent will likely call the __get() method to automatically get the attribute. This will begin a slew of checks, which will return a value or maybe a relationship model. This is extra overhead that may not be needed for this particular part of your application and you could actually be better off just using the query builder without Eloquent. foreach ($cars as $car) { !// }
  15. 3 FRAMEWORK UNDERSTAND ELOQUENT: THE INFAMOUS N+1 We have probably

    all heard about the need to be weary of accessing relationships in loops without eager loading them first as it can lead to N+1 queries being sent to the database. There are a couple of packages that can help with detecting them: 1. beyondcode/laravel-query-detector 2. barryvdh/laravel-debugbar
  16. 3 FRAMEWORK FINDING BOTTLENECKS USING BLACKFIRE.IO When looking for bottlenecks

    in your code, a good tool you can use if Blackfire. It will help understand your code and where the most time is being spent.
  17. 3 FRAMEWORK PREHEATING (IN-MEMORY CACHING) AND QUEUES In-memory caches like

    Redis are very fast can help with storing some data that will be used repeatedly. Preheating the known areas of the application will make those resources super ready for when they are needed.
  18. 3 FRAMEWORK PREHEATING (IN-MEMORY CACHING) AND QUEUES You can also

    return responses before doing further processing like writing to a cache. This can be useful because the user is only subject to the time it took that request to be fulfilled minus the cache write time.