The perfect toolbox to debug performances
Nov. 18th 2015 – viscaweb.com/meetings
2 seconds or less is the time half of the web users expect a site to load.
3G and 4G connections are, days after days, more and more used by users.
20% of traffic and revenue are lost every 500ms of overload.
Impacts on the SEO, Google said the time a website takes to load can impact their position in the search engine.
#WebPerformances
Tools
Tools
Tools
Tools
Tools
Tools
Tools
Tools
Tools
Tools
The perfect toolbox to debug performances
First part:
#WebPerformances
Databases is where most of the web applications
bottlenecks are coming from.
PHP and CPU have their own limits.
You shall reduce as much as you
can the treatments your CPU has to run.
Assets (images, CSS, JS) are performances
killers especially if your applications requires them to work
and/or if must of your users are using a fragile connection (Edge, 3G...).
#WebPerformances
Do NOT do like him,
THINK of a SMART and EFFICIENT strategy
that just works.
MOST of the time, the problem is not PHP, the database or whatever, the problem... is YOU
#WebPerformances
In my humble and personal opinion...
When creating a cache strategy,
here are some questions you must ask yourself at MINIMUM:
#WebPerformances
The perfect toolbox to debug performances
Second part:
#WebPerformances
The next slides are based on a small applications displaying soccer matches for a given date.
This list of matches looks simple but many data are displayed.
#WebPerformances
#WebPerformances
#WebPerformances
Blackfire Profiler automatically instruments your code to gather data about consumed server resources like memory, CPU time, and I/O
#WebPerformances
Let's analyse a profile...
#WebPerformances
The toolbar
#WebPerformances
The toolbar groups as well the SQL queries.
#WebPerformances
#WebPerformances
#WebPerformances
#WebPerformances
loading
loading
#WebPerformances
<p>
Team Home:
{{ match.homeTeam.name }}
<br/>
Result:
{{ match.homeResult.resultText }} -
{{ match.awayResult.resultText }}
<br/>
Team Away:
{{ match.awayTeam.name }}
</p>
/**
* @return Match[]
*/
public function findMatchesWithCommonData()
{
$matches = $this
->createQueryBuilder('match')
->select('match, ht, at, hr, ar')
->join('match.homeTeam', 'ht')
->join('match.awayTeam', 'at')
->join('match.homeResult', 'hr')
->join('match.awayResult', 'ar')
->getQuery()
->getResult();
return $matches;
}
The getters used in Twig (this is just an example) will trigger SQL queries.
This is has a HUGE cost: 4 queries are triggered in this example.
Using joints, we tell Doctrine to load in a single query many information we will always need.
Doctrine will recompose the data and create the proper models/relationships.
#WebPerformances
<?php
use Symfony\Component\Stopwatch\Stopwatch;
$stopwatch = new Stopwatch();
$stopwatch->start('Loading the matches');
// Running SQL queries, hydrations, etc.. [...]
$stopwatch->lap('Loading the matches');
// Calculating some statistics about matches
$event = $stopwatch->stop('Loading the matches');
// The process has finished.
// Display
print "Events:" . PHP_EOL;
foreach($event->getPeriods() as $index => $period){
print sprintf(
"-> Period: %d, duration: %s, memory usage: %s bytes" . PHP_EOL,
$index,
$period->getDuration(),
$period->getMemory()
);
}
#WebPerformances
Events:
-> Period: 0, duration: 1001, memory usage: 524288 bytes
-> Period: 1, duration: 0, memory usage: 524288 bytes
Now, let's couple this component
with your Symfony Application.
Benefit: the time markers will be
displayed in the Symfony Timeline.
#WebPerformances
Declare a new dependency:
Firstly, declare your service:
services:
my_service:
class: My\Service
arguments:
- @?debug.stopwatch
In production, this service is not available. Therefore, the "?" make this service optional.
class MatchListingWidgetRenderer implements Renderer
{
/**
* @param StopWatch $stopWatch StopWatch Component
*/
public function __construct(Stopwatch $stopWatch = null) {
$this->stopWatch = $stopWatch;
}
/**
* @return Response
*/
public function render()
{
if ($this->stopWatch) {
$this->stopWatch->start('Widget: MatchListing');
}
$html = '[...]';
$render = new Response($html);
if ($this->stopWatch) {
$this->stopWatch->stop('Widget: MatchListing');
}
return $response;
}
Use the StopWatch component:
#WebPerformances
#WebPerformances
The perfect toolbox to debug performances
Third part:
#WebPerformances
#WebPerformances
Writing code is easy, thinking code is hard.
Imagining your code, part by part, and by splitting the responsibilities will help you to organise your code.
Thus, don't be stupid by just writing code, but think about it before, takes notes on what's the part that can be tricky, and then, develop.
#WebPerformances
In PHP we usually don't have to care about how to memory is handled. However...
– A bad code can easily create many memory leaks.
– It can end up in 500 errors on production (when using real data and huge databases).
#WebPerformances
The Doctrine cache is super important:
#WebPerformances
Assertions:
Allow you to write some tests asserting that a code:
#WebPerformances
function printHello(){ echo "Hello World!"; }
// get the probe main instance
$probe = BlackfireProbe::getMainInstance();
// won't show up in the profile
printHello();
// start the profiling
$probe->enable();
printHello();
// stop the profiling
$probe->close();
// won't show up in the profile
printHello();
Manual Code Instrumentation
By default, BlackFire runs on the whole query.
What if you want to analyse only a specific part of the process?
#WebPerformances
#WebPerformances
forthcoming
"New Relic provides clear visibility into what's happening all day every day.
It makes prioritizing our work and measuring the impact
of our actions visible for the whole team."
forthcoming
#WebPerformances
"New Relic provides clear visibility into what's happening all day every day.
It makes prioritizing our work and measuring the impact of our actions visible for the whole team."
forthcoming
#WebPerformances
HTTP2 is coming with many new features, such as:
#WebPerformances
HTTP2 is coming and might make the whole Internet faster... if we learn how to takes the best from it.
"Half of web users expect a site to load in 2 seconds"
https://www.keynote.com/resources/white-papers/best-practices-mobile-website-design
New Symfony toolbar
http://symfony.com/blog/new-in-symfony-2-8-redesigned-web-debug-toolbar
Xdebug – Enabling Xdebug with PHP Storm
https://www.jetbrains.com/phpstorm/help/configuring-xdebug.html
MySQL – Enabling global MySQL log
http://stackoverflow.com/questions/6479107/how-to-enable-mysql-query-log
MySQL – Enabling slow query log
https://rtcamp.com/tutorials/mysql/slow-query-log/
#WebPerformances
Holywood Principle
https://en.wikipedia.org/wiki/Hollywood_principle
Doctrine – Difference between lazy and eager loading
http://stackoverflow.com/questions/26891658/what-is-the-difference-between-fetch-eager-and-fetch-lazy-in-doctrine
BlackFire – Documentation
https://blackfire.io/getting-started
BlackFire – Assertions
http://blog.blackfire.io/performance-tests.html
BlackFire – Manual Code Instrumentation
http://blog.blackfire.io/manual-instrumentation.html
#WebPerformances
Symfony Stop Watch Component
http://symfony.com/doc/current/components/stopwatch.html
Varnish – Documentation
https://www.varnish-cache.org/docs
NewRelic
http://newrelic.com/
HTTP2
https://http2.github.io/
#WebPerformances
The perfect toolbox to debug performances
Nov. 18th 2015 – viscaweb.com/meetings
by