$30 off During Our Annual Pro Sale. View Details »

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
Tweet

More Decks by David Chang

Other Decks in Programming

Transcript

  1. 2017.12.13
    Laravel TO

    View Slide

  2. Hello! I'm David
    I'm the Backend Team Lead at Chefs Plate.
    You can find me on Twitter and GitHub at
    @davidchchang

    View Slide

  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

    View Slide

  4. Optimizing PHP
    Application
    Performance

    View Slide

  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

    View Slide

  6. Why Performance Matters

    View Slide

  7. Why Performance Matters

    View Slide

  8. Speed Matters
    ❄ Better customer experiences
    ❄ Determines scalability
    ❄ Build and iterate faster
    ❄ Slower performance means more computing
    resources needed = more expensive

    View Slide

  9. Identifying Performance
    Issues
    First step: realizing you have a problem

    View Slide

  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

    View Slide

  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

    View Slide

  12. Finding the Culprit
    Determine where the non-performant code is
    coming from
    "Knowing where to tap"

    View Slide

  13. Knowing where to tap

    View Slide

  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?

    View Slide

  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

    View Slide

  16. View Slide

  17. View Slide

  18. Track execution times with chefsplate/php-profiler!

    View Slide

  19. Example usage of chefsplate/php-profiler

    View Slide

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

    View Slide

  21. Slow DB Queries
    Majority of taps

    View Slide

  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

    View Slide

  23. Adding a database index usually improves query performance
    Source: CodeProject, Benchmarking with indexed views

    View Slide

  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

    View Slide

  25. 20,000+
    milliseconds!!

    View Slide

  26. Offloading reporting logic from PHP to Mongo aggregations

    View Slide

  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

    View Slide

  28. Decoupling Database Tests
    ❄ Improve unit tests by decoupling and mocking
    database calls
    ❄ Don't confuse integration or API tests with unit
    tests

    View Slide

  29. Caching
    For frequently accessed content

    View Slide

  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

    View Slide

  31. Using the Laravel cache + fallback to populate

    View Slide

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

    View Slide

  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

    View Slide

  34. View Slide

  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

    View Slide

  36. View Slide

  37. Expensive Calls
    Not all function calls are made equal

    View Slide

  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

    View Slide

  39. Host-to-host communication is expensive
    Source: Geeks Hangout, The OSI Model

    View Slide

  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)

    View Slide

  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

    View Slide

  42. Performance gains from using Cloudflare CDN

    View Slide

  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

    View Slide

  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

    View Slide

  45. Testing & Dev Processes
    Other areas for optimizations

    View Slide

  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

    View Slide

  47. Performance Testing
    ❄ Performance testing would be ideal to integrate
    into your CI
    ❄ Log ms before and after
    ❄ Maintain a specific level of performance

    View Slide

  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

    View Slide

  49. Improve testing performance with Paratest

    View Slide

  50. Save your life with hirak/prestissimo

    View Slide

  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

    View Slide

  52. There's no turning back once installed

    View Slide

  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!)

    View Slide

  54. Thanks!
    Questions?

    View Slide

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

    View Slide

  56. ❄ Feb 27, 2018: Presentation TBA
    ❄ Apr 25, 2018: Video Chat with Taylor Otwell
    ❄ Jun 20, 2018: Workshop with Adam Wathan
    Upcoming Meetups

    View Slide