Philipp Hasenfratz: schneller Algorithmus - Daten auslesen

Beitrag lesen

Halihallo Andreas

Ich dachte mir, 16.000 Zeilen müsste man doch eigentlich auch recht performant aus einer Flat-File auslesen können, also habe ich das (mit PHP, ich habe alle " aus den Daten entfernt) so versucht:

Jain, die Flat-File müsste schon einige Anforderungen erfüllen, um sie performant
verarbeiten zu müssen. Z. B. würde ich versuchen von der "Textverarbeitung" wegzu-
kommen und eine Lösung über Random-File-Access zu untersuchen. Also alle Datensätze
haben eine fixe Grösse, somit liesse sich bei geordneten IP-Blöcken selbst bei einer
eigenen Lösung schnell eine Art Index entwickeln (mit fseek immer halbieren und so in
log(n) Zeit zum gewünschten Datensatz springen). Aber lassen wir den Index aus:
Durch den wahlfreien Zugriff auf die Datei mit fixer Datensatz Länge lassen sich die
einzelnen Komponenten (IP_FROM, IP_TO) schnell durch deren relativen Position im
Datensatz extrahieren und ein explode würde hinfällig. Grundsätzlich arbeitet explode
ja sehr performant, aber was passiert wirklich? - Explode splittet einen Text und
generiert ein _neues_ Array, neuer Speicher wird allokiert und eine neue Liste wird
aufgebaut. Je nach dem, wie performant die Speicherverwaltung intern von PHP geregelt
ist kann es hier zu Performanceverlust kommen. Bei Datensätzen mit fixer Länge beschränkt
sich das extrahieren von Daten auf einen substr, welcher höchstens ein neuer String
generieren muss (wenn die Variable global definiert ist fällt ein allokieren von neuem
Speicher weg, da die Daten ja per definition gleich lange sind und der global definierte
String genau diese Länge hat [spätestens nach dem ersten Datensatz]).

Aber das war nicht wirklich schnell, hat im Schnitt gut 0,2 Sekunden gedauert. Und wie ich das bedeutend schneller bekommen soll weiß ich auch nicht. Ich habe auch versucht mit einem if, also nur prüfen ob 2. Nummer kleiner als meine Nummer, aber das war kaum schneller. Vielleicht liegt es auch am explode, aber so viel macht das wohl nicht.

Gleicher Vorschlag wie Cheatah: Nummerisch liesse sich dies wohl performanter lösen.
Auch wenn in PHP da nicht unterschieden wird, wird ein String der Länge 4 wohl schneller
verglichen, als ein String mit 15 Zeichen (127.000.000.001).

Und alles in allem(mit Verbindung herstellen und einlesen in PHP) hat das ganze nur noch  0,04 Sekunden gedauert, es war fast 6 mal so schnell.

MySQL arbeitet mit Datensätzen fixer Länge :-)
Nun ja, in C liesse sich das natürlich auch wesentlich schneller realisieren :-)
Datensatz einfach in ein vordefiniertes struct einlesen und die einzelnen Komponenten
vergleichen, wäre IMHO höchst performant!

Dann habe ich mal den Typen von MyISAM auf HEAP verändert, da hat sich auch kaum was getan, lag vermutlich daran dass die Daten so kurz danach noch in irgendeinem Cache lagen.

Tja, oder der HEAP wurde aufgrund grosser Datenmengen in eine Datei ausgelagert...
Kann auch passieren.

Das beste was mir eingefallen war

$fp = fopen("ips.csv","r");
while (!feof($fp)) {
    $buffer = fgets($fp , 21);
    $com = strpos($buffer, ',');
    if((INT) substr($buffer,$com+1,10) >= $dec_ip){
    break;
    }
}

Das hat ja nun wirklich nichts gemacht, aber es liegt immer noch über 0,2 Sekunden. Wieso?

Hm, das heisst doch schon mal Faktor 2 verbessert??? - Das ist doch schon allerhand?
Nun ja, ich kenne die PHP internals nicht, aber ich kann mir vorstellen, dass die
VM von PHP hier Speicher für 6 temporäre Variablen erstellt.

- $buffer
 - 21 wird skalarer Wert, der fgets übergeben wird
 - $com
 - ',' => wird skalarer Wert, der strpos übergeben wird
 - $com+1 wird skalarer Wert, der substr übergeben wird
 - 10 wird skalarer Wert, der substr übergeben wird

Wenn die C-internen Umsetzungen von fgets, strpos und substr mit *char arbeiten[1],
wären es immer noch zwei Variablen, die allokiert werden müssen (und die werden wohl
auch immer vor der Verwendung auf deren Typ und evtl. Inhalt geprüft).

[1] wovon ich (fast) überzeugt bin

Keine Ahnung wie Zend funktioniert, ich habe nur die letzte Zeit etwas über die internas
von Perl nachgedacht und war schockiert! - Wenn ich Computer wäre, würde ich mich bei
meinem Arbeitgeber wegen "zuvielen sinnlosen und redundanten Arbeiten" beschweren! :-)

---

BTW: Ist das langsam? - 0.4 / 0.2 Sekunden für 16'000 Datensätze[1]? - Ich halte 0.04 von
der Datenbank eher für sehr schnell... Oder traue ich den Computern zuwenig zu?

[1] und 4GL Language PHP/Perl

Viele Grüsse

Philipp