Prestandaöverväganden
Prestandaöverväganden
Vi har redan nämnt i föregående avsnitt att endast insamlingen av möjliga rötter hade en mycket liten prestandapåverkan, men detta är när du jämför PHP 5.2 med PHP 5.3. Även om registreringen av möjliga rötter, jämfört med att inte registrera dem alls som i PHP 5.2, är långsammare, förhindrade andra förändringar i PHP:s körning i PHP 5.3 att denna specifika prestandaförlust ens visades.
Det finns två huvudsakliga områden där prestandan påverkas. Det första området är minskad minnesanvändning, och det andra området är körningstidsfördröjning när skräpsamlingsmekanismen utför sin minnesstädning. Vi kommer att titta på båda dessa frågor.
Minskad minnesanvändning
Först och främst är hela anledningen till att implementera skräpsamlingsmekanismen att minska minnesanvändningen genom att städa upp cirkulärrefererade variabler så snart förutsättningarna är uppfyllda. I PHP:s implementering händer detta så snart rotbufferten är full, eller när funktionen `gc_collect_cycles()` anropas. I grafen nedan visar vi minnesanvändningen för skriptet nedan, i både PHP 5.2 och PHP 5.3, exklusive det basminne som PHP själv använder vid uppstart.
Exempel #1 Minnesanvändningsexempel
<?php class Foo { public $var = '3.14159265359'; public $self; } $baseMemory = memory_get_usage(); for ($i = 0; $i <= 100000; $i++) { $a = new Foo; $a->self = $a; if ($i % 500 === 0) { echo sprintf('%8d: ', $i), memory_get_usage() - $baseMemory, "\n"; } } ?>
Jämförelse av minnesanvändning mellan PHP 5.2 och PHP 5.3
I detta mycket akademiska exempel skapar vi ett objekt där en egenskap pekar tillbaka på objektet självt. När variabeln `$a` i skriptet tilldelas på nytt i nästa iteration av loopen, skulle en minnesläcka typiskt uppstå. I detta fall läcker två zval-behållare (objektets zval och egenskapens zval), men endast en möjlig rot hittas: variabeln som avallokerades. När rotbufferten är full efter 10 000 iterationer (med totalt 10 000 möjliga rötter), aktiveras skräpsamlingsmekanismen och frigör minnet associerat med dessa möjliga rötter. Detta kan mycket tydligt ses i den hackiga minnesanvändningsgrafen för PHP 5.3. Efter varje 10 000 iterationer aktiveras mekanismen och frigör minnet associerat med de cirkulärrefererade variablerna. Mekanismen själv behöver inte göra så mycket arbete i detta exempel, eftersom strukturen som läcker är extremt enkel. Från diagrammet ser du att den maximala minnesanvändningen i PHP 5.3 är cirka 9 MB, medan minnesanvändningen i PHP 5.2 fortsätter att öka.
Körningstidsfördröjningar
Det andra området där skräpsamlingsmekanismen påverkar prestandan är den tid det tar när skräpsamlingsmekanismen aktiveras för att frigöra det "läckta" minnet. För att se hur mycket detta är, modifierar vi något det tidigare skriptet för att tillåta ett större antal iterationer och tar bort de mellanliggande minnesanvändningsutskrifterna. Det andra skriptet är här:
Exempel #2 Påverkan på GC-prestanda
<?php class Foo { public $var = '3.14159265359'; public $self; } for ($i = 0; $i <= 1000000; $i++) { $a = new Foo; $a->self = $a; } echo memory_get_peak_usage(), "\n"; ?>
Vi kommer att köra detta skript två gånger, en gång med inställningen `zend.enable_gc` aktiverad, och en gång med den avaktiverad:
Exempel #3 Körning av ovanstående skript
time php -dzend.enable_gc=0 -dmemory_limit=-1 -n example2.php # och time php -dzend.enable_gc=1 -dmemory_limit=-1 -n example2.php
På min maskin verkar det första kommandot konsekvent ta cirka 10,7 sekunder, medan det andra kommandot tar cirka 11,4 sekunder. Detta är en fördröjning på cirka 7%. Dock minskas den maximala mängden minne som används av skriptet med 98% från 931 MB till 10 MB. Detta riktmärke är inte särskilt vetenskapligt, eller ens representativt för verkliga applikationer, men det demonstrerar de minnesanvändningsfördelar som denna skräpsamlingsmekanism ger. Det positiva är att fördröjningen alltid är samma 7% för detta specifika skript, medan minnesbesparingen ökar ju fler cirkulära referenser som hittas under skriptexekveringen.
PHP:s interna GC-statistik
Det är möjligt att få fram lite mer information om hur skräpsamlingsmekanismen körs från inom PHP. Men för att göra det måste du rekompilera PHP för att aktivera benchmark- och datainsamlingskoden. Du måste ställa in miljövariabeln `CFLAGS` till `-DGC_BENCH=1` innan du kör `./configure` med dina önskade alternativ. Följande sekvens borde göra susen:
Exempel #4 Rekompilera PHP för att aktivera GC-benchmarking
export CFLAGS=-DGC_BENCH=1 ./config.nice make clean make
När du kör ovanstående exempelkod igen med den nykompilerade PHP-binären, kommer du att se följande efter att PHP har avslutat exekveringen:
Exempel #5 GC-statistik
GC Statistics ------------- Runs: 110 Collected: 2072204 Root buffer length: 0 Root buffer peak: 10000 Possible Remove from Marked Root Buffered buffer grey -------- -------- ----------- ------ ZVAL 7175487 1491291 1241690 3611871 ZOBJ 28506264 1527980 677581 1025731
De mest informativa statistiken visas i det första blocket. Här kan du se att skräpsamlingsmekanismen kördes 110 gånger, och totalt frigjordes mer än 2 miljoner minnesallokeringar under dessa 110 körningar. Så snart skräpsamlingsmekanismen har körts åtminstone en gång är "Root buffer peak" alltid 10000.
Slutsats
Generellt sett kommer skräpsamlaren i PHP endast att orsaka en fördröjning när cykelinsamlingsalgoritmen faktiskt körs, medan det i normala (mindre) skript inte bör vara någon prestandapåverkan alls.
Men i de fall där cykelinsamlingsmekanismen körs för normala skript, möjliggör minskningen av minnesanvändningen att fler av dessa skript kan köras samtidigt på din server, eftersom inte så mycket minne används totalt sett.
Fördelarna är mest uppenbara för långvariga skript, såsom långa testsuiter eller demonskript. Även för » PHP-GTK-applikationer som generellt tenderar att köras längre än webbskript, bör den nya mekanismen göra stor skillnad när det gäller minnesläckor som uppstår över tid.
Sidslut
Orginalhemsidan på Engelska :https://www.php.net/manual/en/features.gc.performance-considerations.php
Det här är en maskinöversättning av PHP-manualen till svenska. Om du hittar fel är vi tacksamma om du rapporterar dem via formuläret som finns på
https://www.linux.se/kontaka-linux-se/
Tack till Datorhjälp.se som har sponsrat Linux.se med webserver.