[PHP] unserialize sprengt Speicherlimit

Flot

Member
ID: 347882
L
12 Juli 2009
11
1
Hallo,

Ich stehe vor einem Problem, ich muss Daten aus einer Schnittstelle auslesen, doch überschreitet der Arbeitsspeicherbedarf anscheinend die 50 MB die für die Scripte maximal zugelassen werden.
Ich benutze folgenden Code um an die Daten zu kommen.

PHP:
echo 'bimport'.memory_get_usage().'<br>';
$file = file("https://allprojectstats.com/export.php?id=".$this->id);
echo 'afiliimport'.memory_get_usage().'<br>';
$implode = implode("",$file);
unset($file);//speicherleerung- - - - - 
echo 'aimplode'.memory_get_usage().'<br>';
$gzip = gzuncompress($implode);
unset($implode);//speicherleerung- - - - - 
echo 'agzip'.memory_get_usage().'<br>';
$this->data = unserialize($gzip);

Das funktioniert auch soweit nur gibt es gewisse Teams die eben die 50 MB überschreiten. Kann ich das irgendwie in der Zwischenzeit auf die Festplatte legen oder so, damit ich nicht den Arbeitsspeicher belaste, oder muss ich trotzdem irgend wann alles zusammen laden? $gzip ist bevor versucht wird es in Daten umzuwandeln ca 20 MB groß.
Weiß wer wie ich das trotzdem zum laufen bekomme?

Würde mich über eure Hilfe freuen.

Grüße Flot
 
Hm... partielles Deserialisieren gibt es bei PHP meines Wissens nicht. Wenn die Daten komprimiert schon 20MB groß sind, werden sie entpackt auch weit über 50MB groß sein. Die einzige Lösung bei solchen Datenmengen dürfte eine Erhöhung des Memory-Limits sein.

Greetz

paddya
 
Kein Plan, ob's dann in den Speicherlimits ist, aber Du hast auf jeden Fall jede Menge Daten im Speicher, die Du nicht mehr brauchst, wenn ich das richtig sehe. $file und $implode sind schon verarbeitet zu $gzip, also dödeln die unnütz im Speicher rum. Versuch mal, die mittels unset() freizugeben - mit 'ner gehörigen Menge Glück passt das dann vielleicht mit dem Speicher.
 
Hm... partielles Deserialisieren gibt es bei PHP meines Wissens nicht.
Niemand hindert einen aber, es zu implementieren ;)
Ob sich das aber lohnt, steht auf einem anderen Papier. Ich würde in diesem Fall das Speicherlimit erhöhen. Große Daten brauchen auch viel Speicher, von daher ist das nicht verkehrt, wenn man sonst schon sparend mit dem Speicher umgegangen is und es trotzdem nicht reicht.
 
Hi,

Ich kann das Memory Limit leider nicht weiter erhöhen.

Gibt es eine Möglichkeit im Script selber das Speicherlimit zu erhöen?
Gibt doch auch was um die max runtime zu umgehen oder?


@ tleilax
Schau mal in Zeile 5 und 8 steht doch dort, sogar ein Kommentar das ich den Speicher leere ;)
Das hat zwar die Zahl der möglichen Importe erhöt, aber es gibt noch immer größere.


Grüße Flot
 
mit 'ner gehörigen Menge Glück passt das dann vielleicht mit dem Speicher.
wenn der Garbage Collector von PHP zu dem Zeitpunkt nicht laufen will, hat man auch damit kein Glück, aber kurz vor dem Memory Limit sollte er dann eigentlich laufen, hmm, man findet gar keine Dokumentation, wie der PHP-Garbage-Collector arbeitet :-?

Niemand hindert einen aber, es zu implementieren ;)
Ob sich das aber lohnt, steht auf einem anderen Papier.
das serialize-Format von PHP ist eigentlich sehr simpel, das sollte also gar nicht soviel Arbeit sein. Man muss ja nichtmal einen komplett eigenen Deserializer bauen, es reicht ja den großen Block in mehrere Chunks zu unterteilen, die man wieder durch unserialize() jagen kann.
 
das serialize-Format von PHP ist eigentlich sehr simpel, das sollte also gar nicht soviel Arbeit sein.
Ich dachte mit "lohnt" auch eher, ob es überhaupt funktioniert, da der Deserializer ja selber wieder Speicher braucht, da sicherlich Teile (bei deiner Idee mit den Chunks: sogar große) des ursprünglichen Strings abkopiert werden müssen, da nicht wie in C auf demselben Stück Speicher gearbeitet werden kann.
 
Zuletzt bearbeitet:
Also wenn alles nichts hilft und du auch vor einer laengeren umstrukturierung nicht zurueckschreckst empfehl ich das ganz in einen online algorithmus umzuwandeln.
Indem du immer schoen mit fopen, fseek, etc arbeitest kannst du deinen Speicherbedarf fast konstant halten. Liess einfach immer nur das was du gerade brauchst, und dann verwirf die Daten aus der memory.

Ich denke ja nicht dass du alle 50MB fuer random access brauchst. Ausserdem wird dein script dadurch wesentlich "reaktiever" weil es zwischendurch Meldungen zurueckgeben kann wie etwa 50% vom Download sind abgeschlossen und so ^^