it-swarm.com.de

Wie kann ich die Speichergröße einer Variablen ermitteln?

Gibt es eine Funktion in PHP (oder einer PHP - Erweiterung), um herauszufinden, wie viel Speicher eine bestimmte Variable benötigt? sizeof sagt mir nur die Anzahl der Elemente/Eigenschaften.

memory_get_usage hilft dabei, dass mir die vom whole script verwendete Speichergröße zur Verfügung gestellt wird. Gibt es eine Möglichkeit, dies für eine einzelne Variable zu tun?

Beachten Sie, dass sich dies auf einem Entwicklungscomputer befindet. Das Laden von Erweiterungen oder Debugging-Tools ist daher möglich.

96
Piskvor

Sie benötigen wahrscheinlich einen Speicher-Profiler. Ich habe Informationen gesammelt SO, aber ich habe einige wichtige Dinge kopiert, die auch Ihnen helfen können.

Wie Sie wahrscheinlich wissen, hat Xdebug die Unterstützung der Speicherprofilierung seit der 2. * Version eingestellt. Suchen Sie hier nach der Zeichenfolge "entfernte Funktionen": http://www.xdebug.org/updates.php

Entfernte Funktionen

Die Unterstützung für das Memory-Profiling wurde entfernt, da dies nicht ordnungsgemäß funktioniert hat.

Andere Profiler-Optionen

pHP-Speicher-Profiler

https://github.com/arnaud-lb/php-memory-profiler . Ich habe dies auf meinem Ubuntu-Server getan, um es zu aktivieren:

Sudo apt-get install libjudy-dev libjudydebian1
Sudo pecl install memprof
echo "extension=memprof.so" > /etc/php5/mods-available/memprof.ini
Sudo php5enmod memprof
service Apache2 restart

Und dann in meinem Code:

<?php
memprof_enable();
// do your stuff
memprof_dump_callgrind(fopen("/tmp/callgrind.out", "w"));

Öffnen Sie schließlich die callgrind.out-Datei mit KCachegrind

Google gperftools verwenden (empfohlen!)

Installieren Sie zunächst die Google gperftools, indem Sie das neueste Paket hier herunterladen: https://code.google.com/p/gperftools/

Dann wie immer:

Sudo apt-get update
Sudo apt-get install libunwind-dev -y
./configure
make
make install

Jetzt in deinem Code:

memprof_enable();

// do your magic

memprof_dump_pprof(fopen("/tmp/profile.heap", "w"));

Dann öffne dein Terminal und starte:

pprof --web /tmp/profile.heap

pprof erstellt ein neues Fenster in Ihrer vorhandenen Browsersitzung mit dem folgenden Beispiel:

PHP memory profiling with memprof and gperftools

Xhprof + Xhgui (das beste meiner Meinung nach, um sowohl die CPU als auch den Speicher zu profilieren)

Mit Xhprof und Xhgui können Sie auch die CPU-Auslastung oder nur die Speicherauslastung erfassen, wenn dies momentan Ihr Problem ist. __ Es handelt sich um sehr vollständige Lösungen, die Ihnen vollständige Kontrolle und die Protokolle bieten kann sowohl auf Mongo als auch im Dateisystem geschrieben werden.

Für mehr Details siehe hier .

Schwarzes Feuer

Blackfire ist ein PHP Profiler von SensioLabs, der Symfony2-Jungs https://blackfire.io/

Wenn Sie puphpet verwenden, um Ihre virtuelle Maschine einzurichten, werden Sie froh sein, dass sie unterstützt wird ;-)

Xdebug und Ablaufverfolgung des Arbeitsspeichers

XDEBUG2 ist eine Erweiterung für PHP. Mit Xdebug können Sie alle Funktionsaufrufe einschließlich der Parameter protokollieren und Werte in verschiedenen Formaten an eine Datei zurückgeben. Es gibt drei Ausgabeformate. Eine ist als von Menschen lesbare Ablaufverfolgung gedacht, eine andere ist eher für Computerprogramme geeignet, da sie einfacher zu analysieren ist, und der letzte verwendet HTML zum Formatieren der Ablaufverfolgung. Sie können mit der Einstellung zwischen den beiden verschiedenen Formaten wechseln. Ein Beispiel wäre hier verfügbar

für P

forp einfacher, nicht aufdringlicher, produktionsorientierter PHP Profiler. Einige Funktionen sind:

  • zeitmessung und belegter Speicher für jede Funktion

  • CPU auslastung

  • datei- und Zeilennummer des Funktionsaufrufs

  • ausgabe als Trace-Event-Format von Google

  • bildunterschrift von Funktionen

  • gruppierung von Funktionen

  • aliase von Funktionen (nützlich für anonyme Funktionen)

DBG

DBG ist ein voll funktionsfähiger PHP-Debugger, ein interaktives Tool, das Sie beim Debuggen von PHP-Skripts unterstützt. Es funktioniert auf einem Produktions- und/oder Entwicklungs-WEB-Server und ermöglicht Ihnen das lokale oder Remote-Debuggen Ihrer Skripts über eine IDE oder Konsole und die folgenden Funktionen:

  • Remote- und lokales Debugging

  • Explizite und implizite Aktivierung

  • Aufrufstack, einschließlich Funktionsaufrufe, dynamische und statische Methodenaufrufe mit ihren Parametern

  • Navigation durch den Aufrufstapel mit der Möglichkeit, Variablen an entsprechenden (verschachtelten) Stellen auszuwerten

  • Step in/Step out/Schritt über/Cursorfunktion ausführen

  • Bedingte Haltepunkte

  • Globale Haltepunkte

  • Protokollierung für Fehler und Warnungen

  • Mehrere gleichzeitige Sitzungen für das parallele Debugging

  • Unterstützung für GUI- und CLI-Frontends

  • Unterstützte IPv6- und IPv4-Netzwerke

  • Alle vom Debugger übertragenen Daten können optional mit SSL geschützt werden

40
Vineet1982

Es gibt keine direkte Möglichkeit, die Speichernutzung einer einzelnen Variablen abzurufen, aber wie von Gordon vorgeschlagen, können Sie memory_get_usage verwenden. Dadurch wird die Gesamtmenge des zugewiesenen Arbeitsspeichers zurückgegeben. Sie können also eine Problemumgehung verwenden und die Nutzung vor und nach der Nutzung einer einzelnen Variablen ermitteln. Das ist ein bisschen hackig, aber es sollte funktionieren.

$start_memory = memory_get_usage();
$foo = "Some variable";
echo memory_get_usage() - $start_memory;

Beachten Sie, dass dies keinesfalls eine zuverlässige Methode ist. Sie können nicht sicher sein, dass nichts anderes den Speicher berührt, während Sie die Variable zuweisen. Daher sollte dies nur als Annäherung verwendet werden.

Sie können das tatsächlich in eine Funktion umwandeln, indem Sie eine Kopie der Variablen in der Funktion erstellen und den verwendeten Speicher messen. Ich habe das nicht getestet, aber im Prinzip sehe ich nichts falsches daran:

function sizeofvar($var) {
    $start_memory = memory_get_usage();
    $tmp = unserialize(serialize($var));
    return memory_get_usage() - $start_memory;
}
91
Tatu Ulmanen

Nein, da ist kein. Sie können jedoch serialize($var) und die strlen des Ergebnisses auf Annäherung überprüfen.

22
Aistina

Antwort auf Tatu Ulmanens Antwort:

Es sollte beachtet werden, dass $start_memory selbst Speicherplatz (PHP_INT_SIZE * 8) belegt.

So sollte die ganze Funktion werden:

function sizeofvar($var) {
    $start_memory = memory_get_usage();
    $var = unserialize(serialize($var));
    return memory_get_usage() - $start_memory - PHP_INT_SIZE * 8;
}

Es tut mir leid, das als zusätzliche Antwort hinzuzufügen, aber ich kann noch keine Antwort dazu abgeben.

Update: Die * 8 ist nicht eindeutig. Es kann scheinbar von der PHP-Version und möglicherweise von 64/32 Bit abhängen. 

20
para

Sehen:

Beachten Sie, dass Sie dadurch jedoch nicht die Speichernutzung einer bestimmten Variablen erhalten. Sie können diese Funktionen jedoch vor und nach der Zuweisung der Variablen aufrufen und dann die Werte vergleichen. Das sollte Ihnen einen Eindruck von dem verwendeten Speicher vermitteln.

Sie können sich auch die PECL-Erweiterung Memtrack anschauen, obwohl die Dokumentation etwas fehlt, wenn auch nicht praktisch vorhanden ist.

4
Gordon

Sie können sich für die Berechnung der Speicherdifferenz für einen Rückrufwert entscheiden. Dies ist eine elegantere Lösung, die in PHP 5.3 und höher verfügbar ist.

function calculateFootprint($callback) {
    $startMemory = memory_get_usage();
    $result = call_user_func($callback);
    return memory_get_usage() - $startMemory;
}

$memoryFootprint = calculateFootprint(
    function() {
        return range(1, 1000000);
    }
);

echo ($memoryFootprint / (1024 * 1024)) . ' MB' . PHP_EOL;
3
Liviu Bundă

Sie können den genauen Footprint einer Variablen nicht rückwirkend berechnen, da zwei Variablen denselben zugewiesenen Speicherplatz im Speicher teilen können

Versuchen wir, den Speicher zwischen zwei Arrays zu teilen. Wir sehen, dass die Zuweisung des zweiten Arrays die Hälfte des Speichers des ersten Arrays kostet. Wenn wir den ersten deaktivieren, wird fast der gesamte Speicher noch vom zweiten belegt.

echo memory_get_usage()."\n"; // <-- 433200
$c=range(1,100);
echo memory_get_usage()."\n"; // <-- 444348 (+11148)
$d=array_slice($c, 1);
echo memory_get_usage()."\n"; // <-- 451040 (+6692)
unset($c);
echo memory_get_usage()."\n"; // <-- 444232 (-6808)
unset($d);
echo memory_get_usage()."\n"; // <-- 433200 (-11032)

Wir können also nicht schließen, dass das zweite Array die Hälfte des Speichers belegt, da es falsch wird, wenn wir das erste Array entfernen.

Um einen vollständigen Überblick darüber zu erhalten, wie der Speicher in PHP zugewiesen wird und für welche Verwendung, empfehle ich Ihnen, den folgenden Artikel zu lesen: Wie groß sind PHP Arrays (und Werte) wirklich? (Hinweis: GROSS!)

Die Grundlagen der Referenzzählung in der PHP -Dokumentation enthalten auch viele Informationen zur Speichernutzung und Verweise auf freigegebene Datensegmente.

Die verschiedenen Lösungen, die hier vorgestellt werden, eignen sich gut für Annäherungen, aber keine kann die subtile Verwaltung des PHP Speichers bewältigen.

  1. Berechnung des neu zugewiesenen Speicherplatzes

Wenn Sie den neu zugewiesenen Speicherplatz nach einer Zuweisung verwenden möchten, müssen Sie memory_get_usage() vor und nach der Zuweisung verwenden, da die Verwendung mit einer Kopie eine fehlerhafte Sicht auf die Realität ergibt.

// open output buffer
echo "Result: ";
// call every function once
range(1,1); memory_get_usage();

echo memory_get_usage()."\n";
$c=range(1,100);
echo memory_get_usage()."\n";

Denken Sie daran, dass, wenn Sie das Ergebnis der ersten memory_get_usage() speichern möchten, die Variable bereits vorher vorhanden sein muss und memory_get_usage() ein anderes Mal zuvor aufgerufen werden muss, und jede andere Funktion auch.

Wenn Sie wie im obigen Beispiel ein Echo erzeugen möchten, muss der Ausgabepuffer bereits geöffnet sein, um zu vermeiden, dass zum Öffnen des Ausgabepuffers Speicherplatz benötigt wird.

  1. Berechnung des benötigten Platzes

Wenn Sie sich auf eine Funktion verlassen möchten, um den erforderlichen Speicherplatz zum Speichern einer Kopie einer Variablen zu berechnen, berücksichtigt der folgende Code verschiedene Optimierungen:

<?php
function getMemorySize($value) {
    // existing variable with integer value so that the next line
    // does not add memory consumption when initiating $start variable
    $start=1;
    $start=memory_get_usage();
    // json functions return less bytes consumptions than serialize
    $tmp=json_decode(json_encode($value));
    return memory_get_usage() - $start;
}

// open the output buffer, and calls the function one first time
echo ".\n";
getMemorySize(NULL);

// test inside a function in order to not care about memory used
// by the addition of the variable name to the $_GLOBAL array
function test() {
    // call the function name once 
    range(1,1);

    // we will compare the two values (see comment above about initialization of $start)
    $start=1;
    $start=memory_get_usage();
    $c=range(1,100);
    echo memory_get_usage()-$start."\n";
    echo getMemorySize($c)."\n";
}
test();

// same result, this works fine.
// 11044
// 11044

Beachten Sie, dass die Größe des Variablennamens im zugewiesenen Speicher von Bedeutung ist.

  1. Überprüfen Sie Ihren Code !!

Eine Variable hat eine Grundgröße, die durch die innere C-Struktur definiert wird, die im Quellcode PHP verwendet wird. Diese Größe schwankt bei Zahlen nicht. Für Zeichenfolgen wird die Länge der Zeichenfolge hinzugefügt.

typedef union _zvalue_value {
    long lval;                  /* long value */
    double dval;                /* double value */
    struct {
        char *val;
        int len;
    } str;
    HashTable *ht;              /* hash table value */
    zend_object_value obj;
} zvalue_value;

Wenn wir die Initialisierung des Variablennamens nicht berücksichtigen, wissen wir bereits, wie viel eine Variable verwendet (bei Zahlen und Zeichenfolgen):

44 Bytes bei Zahlen

+ 24 Bytes bei Strings

+ die Länge der Zeichenkette (einschließlich des letzten NUL-Zeichens)

(diese Zahlen können sich abhängig von der PHP-Version ändern)

Aufgrund der Speicherausrichtung müssen Sie auf ein Vielfaches von 4 Byte aufrunden. Befindet sich die Variable im globalen Bereich (nicht innerhalb einer Funktion), werden 64 weitere Bytes zugewiesen.

Wenn Sie also einen der Codes auf dieser Seite verwenden möchten, müssen Sie anhand einiger einfacher Testfälle (Zeichenfolgen oder Zahlen) überprüfen, ob das Ergebnis mit diesen Daten übereinstimmt, wobei alle Angaben in diesem Beitrag berücksichtigt werden (Array $ _GLOBAL, erster Funktionsaufruf, Ausgabepuffer, ...)

3
Adam

Ich hatte ein ähnliches Problem und die Lösung, die ich verwendete, bestand darin, die Variable in eine Datei zu schreiben und dann filesize () darauf auszuführen. In etwa so (ungeprüfter Code):

function getVariableSize ( $foo ) 
{
    $tmpfile = "temp-" . microtime(true) . ".txt";
    file_put_contents($tmpfile, $foo);
    $size = filesize($tmpfile);
    unlink($tmpfile);
    return $size;
}

Diese Lösung ist nicht besonders schnell, da sie Festplatten-E/A umfasst. Sie sollte jedoch etwas genaueres als die memory_get_usage-Tricks enthalten. Es hängt nur davon ab, wie viel Präzision Sie benötigen.

2
Alan Bellows
function mesure($var){
    $start = memory_get_usage();
    if(is_string($var)){
        $newValue = $var . '';
    }elseif(is_numeric($var)){
        $newValue = $var + 0;
    }elseif(is_object($var)){
        $newValue = clone $var;
    }elseif(is_array($var)){
        $newValue = array_flip($var, []);
    }
    return memory_get_usage() - $start;
}
1
Abdelilah

Niemals versucht, aber Xdebug-Spuren mit xdebug.collect_assignment s können ausreichen.

1
Arkh

Das folgende Skript zeigt den gesamten Speicherbedarf einer einzelnen Variablen.

function getVariableUsage($var) {
  $total_memory = memory_get_usage();
  $tmp = unserialize(serialize($var));
  return memory_get_usage() - $total_memory; 
}

$var = "Hey, what's you doing?";
echo getVariableUsage($var);

Schau dir das an

http://www.phpzag.com/how-much-memory-do-php-variables-use/

0