Mailinglisten-Archive |
Hallo Liste, ich verarbeite mit einem Script sehr viele Datensätze (sehr große CSV Datei mit ca. 50.000 Zeilen) und baue innerhalb einer Auswertungsklasse ein ebenso großes Array auf. Nun stelle ich dabei seltsame Nebeneffekte fest, nämlich dass ab einer gewissen Menge im Speicher ich nicht mehr auf korrekt auf andere Arrays zugreifen kann. Konkret lese ich die Zeilen einzeln aus dem CSV und mache aus jeder Zeile einen assoziativen Datensatz, den ich dann weiter verarbeite. Es sind Spaltenbezeichnungen als Array in $headers definiert: $headers = array('Anrede', 'Vorname', 'Nachname', 'Strasse', 'Hausnr', 'PLZ', 'Ort'); und ich laufe durch das von fgetcsv zurückgelieferte nicht- assoziative Array $line, um daraus ein assoziatives Array $record zu erstellen: foreach ( $line as $columnKey => $value ) { $record[$headers[$columnKey]] = $value; } Dieser $record wird dann intern zugeordnet und in einem parent Array $records gehalten. Bei 50.000 Datensätzen kommt da sicher ordentlich was im Speicher zusammen, kann ich mir vorstellen. Allerdings ist die Rohdatei (CSV) lediglich 17MB groß und der Server hat 4GB RAM mit zur Scriptlaufzeit abgeschaltetem memory_limit. Die Verarbeitung klappt bis zu einer gewissen Array-Größe problem- los. Dann meldet sich der Interpreter aber mitten im Script mit: Warning: Cannot use a scalar value as an array in /www/htdocs/... Das betrifft dann genau die oben genannte Zeile, in welcher das Array $record unter Berücksichtigung der $headers aufgebaut wird. Und zwar kann die Schleife aus einem mir unerfindlichen Grund plötzlich nicht mehr korrekt auf das Array $headers zugreifen. Der Fehler ist scheinbar aufs Byte genau reproduzierbar. Ich kann mir das Array $headers vor oder nach der betreffenden Scriptzeile mit var_dump oder print_r ausgeben lassen. Ich kann ebenfalls direkt zugreifen mit echo $headers[0]; Aber wenn ich innerhalb der Schleife eine Zeile echo $columnKey.' ('.$headers[$columnKey].') = '.$value.'<br />'; einfüge, dann bringt er mir totale Grütze: 0 (PLZ) = Herr 1 (Ort) = Martin 2 (Array) = Mustermann 3 (Array) = Dorfweg 4 (Array) = 3 5 (Array) = 01234 6 (Array) = Musterstadt Wie man sieht, liefern die ersten Spalten im Zugriff auf das $headers Array noch einen Wert, jedoch den völlig falschen. Er scheint da irgendwo in der Mitte des Arrays zu beginnen, anstatt bei Key 0. Zur Kontrolle ist der Inhalt der Variable $columnKey am Anfang jeder Zeile ausgegeben. Auch ein casting auf Integer habe ich schon probiert. Und ab einer gewissen Spalte liefert der Zugriff auf das eindimensionale Array $headers als Wert selbst nochmal ein Array zurück. Daran stört sich dann auch der Interpreter und bringt die obige Warnung. Um es nochmal auf den Punkt zu bringen: Das Script arbeitet und verarbeitet die Daten korrekt, solange ich eine bestimmte Array-Größe im Speicher nicht erreiche. Wird das interne Array "zu groß", dann erhalte ich diesen oben beschriebenen Effekt. Ich glaube nicht, dass jemand von euch so tiefen Einblick in die PHP Sourcen hat, aber vielleicht ist der Effekt trotzdem bekannt. Oder ist bekannt, welche größe PHP für Arrays im Speicher zulässt bzw. noch korrekt verarbeiten kann? regards, Ringo
php::bar PHP Wiki - Listenarchive