Prestaties beheren
Vroegtijdige optimalisaties zijn de wortel van het kwaad.
Misschien heb je dit citaat al eerder gelezen. Maar ik citeer het graag volledig:
We moeten kleine efficiëntieverbeteringen vergeten, zeg maar 97% van de tijd: voortijdige optimalisatie is de wortel van alle kwaad. Toch mogen we onze kansen in die kritische 3 procent niet voorbij laten gaan.
-- Donald Knuth
Zelfs kleine prestatieverbeteringen kunnen een verschil maken, vooral voor e-commerce websites. Nu de gastenboekapplicatie klaar is voor prime time, laten we eens kijken hoe we de prestaties ervan kunnen controleren.
De beste manier om de prestaties te optimaliseren is door het gebruik van een profiler. De meest populaire optie is tegenwoordig Blackfire (volledige disclaimer: ik ben ook de oprichter van het Blackfire project).
Introductie van Blackfire
Blackfire bestaat uit verschillende onderdelen:
- Een client die profielen activeert (de Blackfire CLI-tool of een browserextensie voor Google Chrome of Firefox);
- Een agent die gegevens voorbereidt en verzamelt voordat ze naar blackfire.io worden gestuurd voor weergave;
- Een PHP-extensie (de probe) die de PHP-code instrumenteert.
Om met Blackfire te werken, moet je eerst een account maken.
Installeer Blackfire op jouw lokale machine door het volgende installatiescript uit te voeren:
1
$ curl https://installer.blackfire.io/installer.sh | bash
Dit installatieprogramma downloadt en installeert de Blackfire CLI Tool.
Als dit uitgevoerd wordt, installeert het de PHP probe in alle beschikbare PHP versies:
1
$ sudo blackfire php:install
Activeer de PHP-probe voor ons project:
1 2 3 4 5 6 7 8 9 10
--- a/php.ini
+++ b/php.ini
@@ -7,3 +7,7 @@ session.use_strict_mode=On
realpath_cache_ttl=3600
zend.detect_unicode=Off
xdebug.file_link_format=vscode://file/%f:%l
+
+[blackfire]
+# use php_blackfire.dll on Windows
+extension=blackfire.so
Herstart de webserver zodat PHP Blackfire kan laden:
1 2
$ symfony server:stop
$ symfony server:start -d
De Blackfire CLI Tool moet worden geconfigureerd met jouw persoonlijke account gegevens (om je projectprofielen op te slaan onder je persoonlijke account). Je kan deze bovenaan de Settings/Credentials
pagina vinden. Voer het volgende commando uit om de plaatsvervangers in te vullen:
1
$ blackfire client:config --client-id=xxx --client-token=xxx
Het opzetten van de Blackfire Agent op Docker
De Blackfire agent service is reeds geconfigureerd in de Docker Compose stack:
Om met de server te kunnen communiceren, moet je jouw persoonlijke server gegevens opvragen (deze gegevens geven aan waar je de profielen wilt opslaan -- je kan er per project één aanmaken); deze kan je onderaan de Settings/Credentials
pagina vinden. Bewaar ze als geheimen:
1 2 3 4
$ symfony console secrets:set BLACKFIRE_SERVER_ID
# xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
$ symfony console secrets:set BLACKFIRE_SERVER_TOKEN
# xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Je kan nu de nieuwe container lanceren:
1 2
$ docker-compose stop
$ docker-compose up -d
Herstellen van een niet-werkende Blackfire installatie
Als je een fout krijgt tijdens het profileren, verhoog dan het Blackfire logniveau om meer informatie in de logs te krijgen:
1 2 3 4 5 6 7
--- a/php.ini
+++ b/php.ini
@@ -10,3 +10,4 @@ zend.detect_unicode=Off
[blackfire]
# use php_blackfire.dll on Windows
extension=blackfire.so
+blackfire.log_level=4
Herstart de webserver:
1 2
$ symfony server:stop
$ symfony server:start -d
En volg de logs:
1
$ symfony server:log
Profileer opnieuw en controleer de uitvoer van de log.
Blackfire in productie configureren
Blackfire is standaard opgenomen in alle Platform.sh projecten.
Zet de server inloggegevens op als productie geheimen:
1 2 3 4
$ symfony console secrets:set BLACKFIRE_SERVER_ID --env=prod
# xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
$ symfony console secrets:set BLACKFIRE_SERVER_TOKEN --env=prod
# xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
De PHP probe is reeds geactiveerd, op dezelfde manier als iedere andere benodigde PHP extensie:
Varnish configureren voor Blackfire
Voordat je kan starten met profileren, moet je een manier vinden om de Varnish HTTP-cache te omzeilen. Zo niet, dan zal Blackfire nooit de PHP-applicatie raken. Je wil alleen toestemming geven voor profielaanvragen die van je lokale machine komen.
Vind jouw huidige IP-adres:
1
$ curl https://ifconfig.me/
En gebruik het om Varnish te configureren:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
--- a/.platform/config.vcl
+++ b/.platform/config.vcl
@@ -1,3 +1,11 @@
+acl profile {
+ # Authorize the local IP address (replace with the IP found above)
+ "192.168.0.1";
+ # Authorize Blackfire servers
+ "46.51.168.2";
+ "54.75.240.245";
+}
+
sub vcl_recv {
set req.backend_hint = application.backend();
set req.http.Surrogate-Capability = "abc=ESI/1.0";
@@ -8,6 +16,16 @@ sub vcl_recv {
}
return (purge);
}
+
+ # Don't profile ESI requests
+ if (req.esi_level > 0) {
+ unset req.http.X-Blackfire-Query;
+ }
+
+ # Bypass Varnish when the profile request comes from a known IP
+ if (req.http.X-Blackfire-Query && client.ip ~ profile) {
+ return (pass);
+ }
}
sub vcl_backend_response {
Je kan nu deployen.
Webpagina's profileren
Je kan traditionele webpagina's van Firefox of Google Chrome profileren via speciale extensies.
Vergeet op jouw lokale machine niet om de HTTP cache uit te schakelen in config/packages/framework.yaml
. Zo niet, dan zal je de Symfony HTTP cache laag in plaats van je eigen code profileren.
Om een beter beeld te krijgen van de prestaties van jouw applicatie in productie, moet je ook een profiel aanmaken van de "productieomgeving". Standaard maakt jouw lokale omgeving gebruik van de "ontwikkelomgeving", die een aanzienlijke overhead toevoegt (voornamelijk voor het verzamelen van gegevens voor de web debug toolbar en de Symfony profiler).
Note
Aangezien we de "productie" omgeving zullen profileren hoeven we niets te wijzigen in de configuratie, omdat we in een vorig hoofdstuk de Symfony HTTP cache laag enkel voor de "ontwikkel" omgeving hebben geactiveerd.
Het overschakelen van jouw lokale machine naar de productieomgeving kan worden gedaan door de APP_ENV
omgevingsvariabele in het .env.local
bestand te wijzigen:
1
APP_ENV=prod
Of je kunt het server:prod
commando gebruiken:
1
$ symfony server:prod
Vergeet niet om aan het einde van jouw profileringssessie terug te schakelen naar dev:
1
$ symfony server:prod --off
API-resources profileren
Het profileren van de API of de SPA kan beter vanaf de CLI worden gedaan via de Blackfire CLI Tool die je eerder hebt geïnstalleerd:
1
$ blackfire curl `symfony var:export SYMFONY_PROJECT_DEFAULT_ROUTE_URL`api
Het blackfire curl
commando accepteert exact dezelfde argumenten en opties als cURL.
Prestaties vergelijken
In de stap over "Cache" hebben we een cache-laag toegevoegd om de prestaties van onze code te verbeteren, maar we hebben de impact van de verandering op de prestaties niet gecontroleerd of gemeten. Omdat je slecht kan raden of een aanpassing alles sneller of net trager maakt, kan het zijn dat je fout raad en je jouw applicatie juist langzamer maakt in plaats van sneller.
Je zou altijd de impact van elke uitgevoerde optimalisatie moeten meten met een profiler. Blackfire maakt dit visueel gemakkelijker dankzij de vergelijkingsfunctie.
Het schrijven van functionele blackboxtesten
We hebben gezien hoe we functionele tests kunnen schrijven met Symfony. Blackfire kan gebruikt worden om surf-scenario's te schrijven die op verzoek via de Blackfire-player kunnen worden uitgevoerd. Laten we een scenario schrijven dat een nieuw commentaar indient en deze valideert via de e-mail link in development en via de admin in productie.
Maak een .blackfire.yaml
bestand aan met de volgende inhoud:
Download de Blackfire-player om het scenario lokaal te kunnen uitvoeren:
1 2
$ curl -OLsS https://get.blackfire.io/blackfire-player.phar
$ chmod +x blackfire-player.phar
Voer dit scenario uit in development:
1
$ ./blackfire-player.phar run --endpoint=`symfony var:export SYMFONY_PROJECT_DEFAULT_ROUTE_URL` .blackfire.yaml --variable "webmail_url=`symfony var:export MAILER_WEB_URL 2>/dev/null`" --variable="env=dev" -vv
1
$ rm blackfire-player.phar
Of in productie:
1
$ ./blackfire-player.phar run --endpoint=`symfony cloud:env:url --pipe --primary` .blackfire.yaml --variable "webmail_url=NONE" --variable="env=prod" -vv
Blackfire-scenario's kunnen ook profielen triggeren voor elke request en prestatietests uitvoeren door het toevoegen van de --blackfire
parameter.
Automatiseren van performancecontroles
Het managen van de prestaties is niet alleen het verbeteren van de prestaties van bestaande code, maar ook het controleren of er geen prestatie-regressies worden geïntroduceerd.
Het scenario dat in de vorige paragraaf is beschreven, kan automatisch worden uitgevoerd in een Continuous Integration-workflow of op regelmatige basis in productie.
Platform.sh maakt het mogelijk om de scenario's uit te voeren wanneer je een nieuwe branch maakt of deployed naar productie om de prestaties van de nieuwe code automatisch te controleren.