Performance is critical to eCommerce businesses, having a direct impact on cart abandonment rate. There’s countless statistics about this. What is missing is the right tools and the best practices. Before even setting up Content Delivery Networks or aiming for low hanging fruits such as images compression, the first thing to look at is the PHP code.
Fabien Potencier and Jacques Bodin-Hullin presented some do’s and don’ts in PHP code performance on Magento 2, what profiling is, and how profiling in development, test, staging and production makes it possible to proactively improve performance. They also unveiled testing strategies which make it possible to automate validation of code iterations with continuous integration and continuous deployment strategies.
5. blackfire.io @blackfireio # blackfireio
Understanding the overhead
● Instrumentation
● Tools ready for production vs tools made for
development only
● Instrumenting all requests vs specific requests
6. blackfire.io @blackfireio # blackfireio
Profiling is about measuring how much
resources your code is consuming
Wall time I/O CPU
Memory Network SQLHTTP Time
https://blackfire.io/docs/24-days/07-time-flavors
7. blackfire.io @blackfireio # blackfireio
Time is volatile
● Time is not a stable metric. External factors such as machine load can
have significant impacts on wall time between two profiles of identical
code.
● Time is just a consequence of what happened in the code
● Use time to identify the slow parts in your code and then:
○ iterate and compare
○ write assertions on the root cause
● Profiling is about understanding how code works at runtime
https://blackfire.io/docs/24-days/12-tests-best-pratices
8. blackfire.io @blackfireio # blackfireio
Callgraphs, timelines and more
● Find the function calls that
consume the most resources
● Know where to stop optimizing
● Trade-off time vs memory and
performance vs code complexity
● Profiling should not always be a
lonely activity
15. blackfire.io @blackfireio # blackfireio
The main issues
● SQL Queries
● Network
● CPU Time
● Memory
● I/O Wait
● External HTTP requests
● PHP & Bad PHP code 🎉
16. blackfire.io @blackfireio # blackfireio
SQL Queries
● Use indexes and correct types.
● Limit the number of results you need.
● Avoid SQL requests…
● If you can’t avoid them, cache the output or
use LocalStorage/CacheStorage if insensitive information.
● Use Magento Repositories.
SQL Requests are the main issue.
18. blackfire.io @blackfireio # blackfireio
CPU Time
● Avoid consuming operations: loops, events…
● Use Magento Repositories.
● KISS : Keep It Simple Stupid.
19. blackfire.io @blackfireio # blackfireio
Memory
● Use the MagentoFrameworkModelResourceModelIterator for your
loops.
● Use PHP! Avoid creating so many objects when you can do the
operation with one function call.
● Use the Magento Dependency Injection.
● Use Magento Repositories.
20. blackfire.io @blackfireio # blackfireio
I/O Wait
● Use php://memory and php://temp. Because Memory is always faster
than I/O.
● Optimize composer: composer dump-autoload --optimize --no-dev
21. blackfire.io @blackfireio # blackfireio
External HTTP Requests
● Don’t do that.
● If you really have to: use RabbitMQ.
● And if you really have no choice: use asynchronous?
● And if you really really have no choice: use a small timeout and deal with
the errors properly.
23. blackfire.io @blackfireio # blackfireio
PHP & Bad PHP code 🎉
● Upgrade to the latest version of PHP.
● Prefer a PHP core function to a lot of objects and methods.
25. blackfire.io @blackfireio # blackfireio
The metrics
● Is Magento 2 installed? CE or EE?
● Is the cache enabled?
● Cache manipulation.
● Product loads.
● Interceptors measurement.
● Mode detector: production/developer/default.
● …
26. blackfire.io @blackfireio # blackfireio
The metrics
magento2.all.cache.full_page.builtin.hit:
label: "Hit full page cache using builtin"
matching_calls:
php:
- callee: "=Magento[…]BuiltinPlugin::addDebugHeader"
caller: "=Magento[…]BuiltinPlugin::aroundDispatch"
27. blackfire.io @blackfireio # blackfireio
The metrics
mymetrics.image.operation:
matching_calls:
php:
- callee: "/.*image.*/"
Will match imagecreate, getimagesize etc.
28. blackfire.io @blackfireio # blackfireio
The recommendations
'The Magento 2 Full Page Cache should be enabled':
assertions:
- 'metrics.magento2.[…]full_page.builtin.hit.count == 1'
exclude:
- '.*/checkout.*'
- '.*/customer/section/load'
- '.*/catalogsearch'
[…]
29. blackfire.io @blackfireio # blackfireio
The recommendations
'Do not make any image operation':
assertions:
- 'metrics.mymetrics.image.operation.count == 0'
30. blackfire.io @blackfireio # blackfireio
Put some limits: .blackfire.yml
tests:
Pages should be fast enough:
path: /.*
assertions:
- main.wall_time < 850ms
- main.io < 500ms
- main.cpu_time < 500ms
Pages should not consume too much memory:
path: /.*
assertions:
- main.memory < 50M
- main.peak_memory < 75M
Homepage should not do too many SQL queries:
path: /
assertions:
- metrics.sql.queries.count <= 12
Checkout pages should be light:
path: /checkout/.*
assertions:
- metrics.output.network_out < 100KB