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

Performance Tuning your Laravel & PHP Applications

David Chang
December 13, 2017

Performance Tuning your Laravel & PHP Applications

Do you find your applications have started to become sluggish over time due to software bloat? Are your APIs taking seconds to return a response? In this month's talk, David Chang from Chefs Plate will be focusing on how to get started with addressing performance issues within your applications, and will talk about lessons they've learnt while improving their average API response times from over a second to sub-200 milliseconds.

David Chang

December 13, 2017

More Decks by David Chang

Other Decks in Programming


  1. 2017.12.13 Laravel TO

  2. Hello! I'm David I'm the Backend Team Lead at Chefs

    Plate. You can find me on Twitter and GitHub at @davidchchang
  3. We're Hiring (Intermediate/Senior) Front-End Developer Data Engineer Product Owner -

    Mobile IT Administrator Plus many more! Check out https://www.chefsplate.com/careers
  4. Optimizing PHP Application Performance

  5. Performance Checklist ❄ Why performance matters ❄ Identifying performance issues

    ☆ Finding the culprit (with profiling) ❄ Tackling root causes: ☆ Slow database queries ☆ Caching non-performant results ☆ Expensive function calls and operations ❄ Improving testing and development processes
  6. Why Performance Matters

  7. Why Performance Matters

  8. Speed Matters ❄ Better customer experiences ❄ Determines scalability ❄

    Build and iterate faster ❄ Slower performance means more computing resources needed = more expensive
  9. Identifying Performance Issues First step: realizing you have a problem

  10. “I'm not a real programmer. I throw together things until

    it works then I move on. The real programmers will say: “Yeah, it works but you're leaking memory everywhere. Perhaps we should fix that". I'll just restart Apache every 10 requests.” - Rasmus Lerdorf
  11. 80:20 rule (more like 95:5) ❄ Most of the times,

    5-10% of your code base is causing 95%+ of your performance issues ❄ Performance dips tend to be tied to code releases ❄ Sometimes massive traffic can reveal infrastructure inadequacies
  12. Finding the Culprit Determine where the non-performant code is coming

    from "Knowing where to tap"
  13. Knowing where to tap

  14. Questions to Ask ❄ How long do your pages take

    to load? ❄ Is every request slow? ☆ What are your most frequently-used pages and endpoints? ☆ Is there any code in common across those pages? ❄ Did we release something recently that caused the slowdown?
  15. Cue: Application Performance Monitoring ❄ APMs like New Relic and

    Datadog help to reveal underlying performance issues ❄ View high level performance metrics with enough granularity of specific issues ❄ Can define thresholds for acceptable performance and set up monitoring notifications to get notified when application performance degrades
  16. None
  17. None
  18. Track execution times with chefsplate/php-profiler!

  19. Example usage of chefsplate/php-profiler

  20. When It's Not Your Code ❄ It could be an

    infrastructure issue
  21. Slow DB Queries Majority of taps

  22. Creating Database Indexes ❄ Look-ups and queries perform dramatically faster

    with the right indexes ❄ Look at what is frequently accessed in your queries ❄ There are some caveats: ☆ Don't index everything ☆ Order of indexes can matter as well
  23. Adding a database index usually improves query performance Source: CodeProject,

    Benchmarking with indexed views
  24. Offloading to the Database ❄ Offload as much of the

    application code back to the database wherever possible ❄ Don't fetch objects into PHP and parse/populate them when you can do it straight in the DB ❄ Utilize built-in aggregation and reporting frameworks if available
  25. 20,000+ milliseconds!!

  26. Offloading reporting logic from PHP to Mongo aggregations

  27. Create-if-not-exists Queries ❄ Generating random unique numbers can be expensive

    on larger tables/collections ☆ One solution: Retryable writes with unique indexes will throw errors; catch exceptions instead of querying for matches
  28. Decoupling Database Tests ❄ Improve unit tests by decoupling and

    mocking database calls ❄ Don't confuse integration or API tests with unit tests
  29. Caching For frequently accessed content

  30. Caching Guidelines ❄ Cache frequently accessed content ☆ Especially if

    the content doesn't change often ❄ Useful for "aggregated" content ☆ e.g. content that requires multiple DB queries to assemble ❄ Always provide a fallback in case caching fails ❄ Make sure to wrap appropriate exception handling logic around your cache calls
  31. Using the Laravel cache + fallback to populate

  32. Cache entire Laravel responses with Spatie's response cache package

  33. ❄ Great for caching entire responses ☆ Considers input parameters

    when caching ❄ Caching on a per-endpoint basis ❄ Not too much flexibility in busting caches ☆ All-or-nothing approach Spatie Response Cache
  34. None
  35. ❄ Save calls to the database for commonly accessed immutable

    data ❄ Only first call to a singleton entity should incur a performance hit ❄ Retrieve further entities from memory directly ❄ Similar to APC cache Singleton Entities
  36. None
  37. Expensive Calls Not all function calls are made equal

  38. "Performance problems in ecommerce are almost always due to making

    too many calls rather than the response time of any given call." — Kelly Goetsch, eCommerce in the Cloud
  39. Host-to-host communication is expensive Source: Geeks Hangout, The OSI Model

  40. Start Low Level ❄ Start from the bottom and then

    work your way up ☆ Database ☆ Laravel MVC Framework ▪ Data/persistence layer (with Eloquent ORM/Doctrine ODM) ▪ Domain layer (models) ▪ Middleware ▪ Controllers ☆ Templates and Views (Frontend)
  41. ❄ Improve performance by serving up assets closer to your

    user base ❄ Reduce load on your web servers ❄ Automatic mobile image optimizations ❄ Leverage gains from GZIP compression and HTTP/2 server push Content Delivery Networks
  42. Performance gains from using Cloudflare CDN

  43. Some Things We've Tried ❄ Swapping out Hash::check bcrypt calls

    with native SHA1 hashing via hash() ☆ Hashing operation went from 192ms to 4ms ❄ Enabling APCu caching for Doctrine metadata: ☆ Saved ~60ms per request
  44. ❄ Replacing splat type-hints (Class … $val) syntax with plain

    array setting ☆ This ended up being 3X faster ❄ Removing magic setters and getters ☆ ~0.0009ms - not worth it! Some Things We've Tried
  45. Testing & Dev Processes Other areas for optimizations

  46. "Only conducting performance testing at the conclusion of system or

    functional testing is like conducting a diagnostic blood test on a patient who is already dead." — Scott Barber
  47. Performance Testing ❄ Performance testing would be ideal to integrate

    into your CI ❄ Log ms before and after ❄ Maintain a specific level of performance
  48. Speeding Up your Testing ❄ Extract out your database calls

    ❄ Mock expensive or difficult to reproduce calls (esp. third party) ❄ Run tests in parallel ❄ Build in performance into your development considerations ☆ Overall speed up of your CI process
  49. Improve testing performance with Paratest

  50. Save your life with hirak/prestissimo

  51. Save your Life with prestissimo ❄ Makes composer installs at

    least ten times faster ❄ Just type: composer global require hirak/prestissimo ☆ There's no turning back ❄ Our installs went from 15+ minutes to 17 seconds ❄ TODO: Buy this guy a beer
  52. There's no turning back once installed

  53. Recap Use APMs and profilers to help you identify performance

    issues Apply indexing and caching techniques & avoid expensive calls Profit! (even more than usual!)
  54. Thanks! Questions?

  55. Happy Holidays and a Happy New Year! From your @LaravelTO

  56. ❄ Feb 27, 2018: Presentation TBA ❄ Apr 25, 2018:

    Video Chat with Taylor Otwell ❄ Jun 20, 2018: Workshop with Adam Wathan Upcoming Meetups