Prestandaöverväganden: Skillnad mellan sidversioner

Från Wiki.linux.se
Hoppa till navigering Hoppa till sök
(Skapade sidan med '=== 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 o...')
 
(Ingen skillnad)

Nuvarande version från 5 oktober 2024 kl. 08.08

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

PHP

Funktioner


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.