Apache Lesegeschwindigkeit langsamer als lokaler Mac



Claudio87

New Member
Hallo zusammen,

habe ein ungewöhnliches Problem. Ich lese auf meinem Server große CSV Files Zeile für Zeile ein. Es handelt sich im Beispiel um 400.000 Zeilen.

Nun benötigt mein MacBook Pro mit einer Xampp Umgebung 8 Sekunden, der Server ganze 19 Sekunden.

Beim MacBook handelt es sich um einen i5, 8GB RAM und SSD.
Der Server hat 8 Cores mit 2,3 GHz, 24 GB RAM und ebenfalls SSD. Sonst laufen am Server keine rechenintensiven Prozesse.

Wie kann das sein? Von der Hardware muss der Server ja deutlich überlegen sein?!

Kann ich an Apache Einstellungen anpassen, was die Lesegeschwindigkeit erhöht? Die serverload geht während dem Prozess nicht über 1, RAM max. 1 GB beansprucht und es arbeiten 4 von 8 Prozessoren.
 
Es gibt Aufgaben die man sehr gut multithreaden kann und es gibt Aufgaben, welche man praktisch nur als singlethread ausführen kann.

Das hier der Serverload bei 1 liegt spricht auch sehr dafür, dass hier tatsächlich nur ein Thread zum Einlesen genutzt wird. Das ist jedenfalls nichts, was man über den Apachen beeinflussen könnte. Theoretisch könnte man das (vermutete) PHP Skript so verändern, dass die Aufgabe in 2 oder mehr Threads läuft, allerdings sehe ich keinen Nutzen darin, da man nur von einer Datei einliest und hier dann mit race conditions zu kämpfen hat.

Eine vernünftigere Möglichkeit wäre die, dass man die Datei in z.B. 4 Dateien splittet und dann parallel alle 4 Dateien einliest. Da man hier aber natürlich nicht vorhersagen kann, wann welcher Datensatz eingelesen wird, muss man am Ende immer noch einen sort ausführen, falls die Reihenfolge eine entscheidende Rolle spielt. Ob unter diesen Umständen dann ein Geschwindigkeitsvorteil noch da ist, wird man ausprobieren müssen.
 
Last edited by a moderator:
habe ein ungewöhnliches Problem. Ich lese auf meinem Server große CSV Files Zeile für Zeile ein. Es handelt sich im Beispiel um 400.000 Zeilen.

..

Kann ich an Apache Einstellungen anpassen, was die Lesegeschwindigkeit erhöht?

Du könntest statt der Datei ein DBMS nutzen.


--
.A.
 
Theoretisch könnte man das (vermutete) PHP Skript so verändern, dass die Aufgabe in 2 oder mehr Threads läuft
PHP kann nicht threaden, nur forken. Somit kann man nicht die gleiche Variable befüllen was den Vorteil zunichte macht.

Du könntest statt der Datei ein DBMS nutzen.
Datenbanken sind nicht schneller als reines sequentielles Lesen wenn man davon ausgeht dass alle Werte benötigt werden.
In aller Regel wird nicht das Einlesen sondern das Verarbeiten der Werte die Hauptbremse darstellen - wenn ein Cpu-Kern auf dem Server also im Vergleich zum Rechner langsamer ist wird auch das Ergebnis langsamer sein.

CSV ist nicht brauchbar für solche Datenmengen.
Der OP sagt nur dass er die Datei einlesen will - nicht aber ob er die Informationen nur teilweise braucht. Wenn man nun davon ausgeht dass er sie (fast) vollständig haben will wird CSV immer schneller sein als Sqlite - zumal PHP bereits nativ das Einlesen einer Zeile als CSV mittels fgetcsv() beherrscht. Die Dateigröße hat dabei keine Einwirkung auf die Geschwindigkeit.
 
Last edited by a moderator:
PHP kann nicht threaden, nur forken. Somit kann man nicht die gleiche Variable befüllen was den Vorteil zunichte macht.

Hm, mein Fehler. Da ich mit PHP nur einmal in meinem Leben gearbeitet habe, hatte ich gegoogled und es schien eine Möglichkeit zu geben, zumindest fand ich pthreads, scheinbar sogar thread safe.
Sorry, falls ich dann hier für Verwirrung gesorgt habe.

So oder so wären einige Informationen über das Projekt wünschenswert, dann kann man evtl. gezielter helfen.
 
Ich korrigiere. PHP kann _eigentlich_ kein Threading. Die Erweiterung ist sehr selten und setzt einige Voraussetzungen wie Thread-Safety welche mit so einigen anderen Erweiterungen nicht gut zusammenspielt. Für diesen Fall würde es aber evtl tatsächlich ausreichen.
 
Wenn es sich um Single Core Tasks handelt, ist die Geschwindigkeit eines einzelnen Kerns maßgeblich. iX Prozessoren takten hier den Prozessor um mehrere 100Mhz höher (Intel Turbo Boost), wenn nur ein Kern beansprucht wird.

Da Du uns nicht verraten hast, welchen i5 Du hast was das für ein 8-Core Prozessor ist (ich vermute mal ein AMD Opteron?), können wir auch die CPUs hier nicht sinnvoll vergleichen. Es kann gut sein, dass der i5 mit seinen 4 Kernen performanter ist als der 8-Core Prozessor. Du kannst ja mal Deine CPUs auf http://www.cpubenchmark.net/ vergleichen.
 
Datenbanken sind nicht schneller als reines sequentielles Lesen wenn man davon ausgeht dass alle Werte benötigt werden.

Sicher hast Du Recht, wenn es um das reine sequzielle Lesen geht. Ich gehe allerdings davon aus, dass das System sich während des Einlesens langweilt (Load < 1 und optimalerweise max 1 GB von 24 GB RAM für Caching genutzt). Weiter gehe ich davon aus, dass öfter abgefragt werden soll, sonst wären die 10s Unterschied egal.

Und beim gecachten, parallelen sowie ggf. teilweisen Abfragen Daten vertraue ich auf Leute, die seit Jahren diese Operationen optimieren, an Stelle von irgendwie gethreadeden PHP-Skripten o.ä.

In aller Regel wird nicht das Einlesen sondern das Verarbeiten der Werte die Hauptbremse darstellen.

Von verarbeiten spricht der OP allerdings auch nicht.

--
.A.
 
Mit fgetcsv hast du quasi das einlesen und die Verarbeitung in einem. Wenn du mit dem Resultat noch mehr machst, wird es natürlich noch schlimmer.

Eben einfach mal ausprobiert. Dummy CSV mit 400.000 Zeilen und 18 Feldern pro Zeile. Insgesamt 83MB.
Der fgetcsv() braucht bei mir 14 Sekunden und ein einfaches file_get_contents() braucht 0,012 Sekunden. Da merkt man doch schon, dass nicht das einlesen der Datenmenge das Problem ist. Sondern d4f völlig recht hat und die Verarbeitung der CSV Daten das Problem ist. ;)
 
Die eigentliche Frage, so wie ich sie verstehe, lautete, warum derselbe Vorgang, Datenimport und -verarbeitung, auf einem vermeintlich langsameren Laptop länger dauert, als auf einem potenten Server.
Jetzt wäre doch erst mal zu klären, wie es zu dieser Beobachtung kommt. Die hier diskutierten Performanceoptimierungen würden sich ja vermutlich auf beiden Systemen auswirken.

Und bevor Optimierungsmaßnahmen getroffen werden, sollte doch erst eine Analyse erfolgen, wo die Performance überhaupt verloren geht. Beispiel: Beobachtet wurde eine Zeitdifferenz von 11 Sekunden zwischen Laptop und Server. Würde das pure Einlesen auf diesem Server diese 11 Sekunden verursachen (z.B. ein Hardwaredefekt), können alle nachfolgenden Performanceoptimierungen die Zeit nie unter 11 Sekunden drücken. Und das eigentliche Problem ist auch mit dieser vermeintlich maximalen Optimierung immer noch nicht gelöst.

Bei dem Lösungsvorschlag, aus einer Datenbank statt aus einer csv-Datei zu lesen wäre zu berücksichtigen, wie lang das Einlesen der Datei in die Datenbank dauert.
 
Wenn der Threadersteller nicht mitwirkt, kannst du nun mal recht wenig plausibel analysieren. ;)
Der wahrscheinlichste Grund wurde doch schon genannt: Die Single-Thread Performance der CPU.

Mit meinen Werten und der Differenz zwischen einlesen und verarbeiten, dürfte klar sein, dass er bei gleicher Größenordnung und ähnlicher Zeitspanne wohl auch ähnliches macht.
Zwischen einlesen und verarbeiten lag ein zeitlicher Faktor von über 1000. Wenn seine Zeitangabe nur für das einlesen der Daten wäre, würde er beim Minimum an Verarbeitung der Daten rund 4 Stunden brauchen.
Das braucht nicht mal ein 486er wenn ich ihm die 80MB mit zig Disketten verfüttere.

Somit muss man also in dieser Richtung nicht extrem tiefgründig analysieren. Eine simple Wahrscheinlichkeitsrechnung und etwas Praxiserfahrung reichen da vollkommen aus. ;)
 
Vielen Dank für eure sehr ausführlichen Informationen!

Im Grunde ging es mir wirklich primär um die Unterschiede zwischen dem Server und dem Notebook. Allerdings habe ich nun auf Grund der hinweise hier etwas getestet und habe nun eine klasse Lösung gefunden.

Wie schon richtig geschrieben wurde, soll das File ja nicht nur gelesen werden, sondern die Daten darin auch an die Datenbank gesendet bzw. Werte geprüft werden. Das ist sehr rechenlastig und hat für insgesamt aktuell ca. 700.000 Datensätze über 12 Minuten gedauert.

Nun habe ich mein Script so geändert, dass die Anfrage auf mehrere Scripts über curl verteilt wird. Habe 10 multi-curl Operationen am laufen, welche an verschiedenen Punkten in den entsprechenden CSV Files ansetzen.

Somit konnte ich die 700k Sätze in gerade einmal 60 Sekunden inklusive aller Anfragen bei der Datenbank (vorher 12 min) verarbeiten. Hier arbeiten wirklich alle 8 Cores bei etwa 75-80% Auslastung, was zu einer vorübergehenden load von 4-5 führt, aber eben auch nur temporär für 1 Minute.

Besten Dank für die Hinweise!!! :)
 
Back
Top