| 

.NET C# Java Javascript Exception

8
Heute mal etwas skurriles. Eigentlich eine Alltagsaufgabe, die man mit einem 2-Zeiler lösen kann, aber ich bin doch erstaunt über das Problem und die Lösung. Es geht darum, eine Datei auf einem NFS-Share abzulegen, das vorher per PUT zum Webserver hochgeladen wurde. Wahrscheinlich hat man das selbe Problem auch wenn die Datei per POST-Formular hochgeladen […]
Keine ähnlichen Artikel.

Heute mal etwas skurriles. Eigentlich eine Alltagsaufgabe, die man mit einem 2-Zeiler lösen kann, aber ich bin doch erstaunt über das Problem und die Lösung. Es geht darum, eine Datei auf einem NFS-Share abzulegen, das vorher per PUT zum Webserver hochgeladen wurde. Wahrscheinlich hat man das selbe Problem auch wenn die Datei per POST-Formular hochgeladen wurde.

Folgender Aufruf lädt eine Datei via PUT auf einen Webserver:

curl -T 100mb.test http://localhost/put.php

Mein einfaches Testscript, das die Datei auf das NFS-Share legen soll, sieht so aus:

<?
$putdata = fopen("php://input", "r");
file_put_contents('/mnt/nfs/100mb.zip', $putdata);

Es dauert knapp 26 Sekunden bis das Script fertig ist bei einer 100MB Datei. Das muss doch schneller gehen! 4MB/s ist viel zu wenig für ein Gigabit-Netzwerk und einen schnellen NFS-Storage.

Nächster Versuch:

<?
$putdata = fopen("php://input", "r");
file_put_contents('/tmp/100mb.zip', $putdata);
copy('/tmp/100mb.zip', '/mnt/nfs/100mb.zip');

Hier gehe ich den Umweg über die lokale Festplatte. Ich speichere die Datei erst lokal auf dem Webserver, und kopiere sie dann auf das NFS-Share. Das file_put_contents() auf die lokale Festplatte dauert knapp 1 Sekunde, das ist kein Problem. Aber der copy()-Befehl ist wieder recht langsam, 21 Sekunden, sprich 5MB/s. Was ist denn nur los?

(Die PHP-Funktion rename(), die normalerweise dafür das ist eine Datei zu verschieben, kann ich nicht nutzen da man die Funktion nur zum Verschieben auf einer Partition nutzen kann, und ich die Datei auf ein NFS-Share ablegen möchte.)

Um mich zu vergewissern dass es nicht am Netzwerk oder am NFS-Storage liegt mache ich einen Test per SSH:

time cp 100mb.zip /mnt/nfs/100mb.zip

real    0m4.236s
user    0m0.007s
sys     0m0.144s

Aha! Es geht doch! 4 Sekunden, sprich 25MB/s, das ist doch schon viel besser.

Nächster Versuch:

<?
$putdata = fopen("php://input", "r");
file_put_contents('/tmp/100mb.zip', $putdata);
shell_exec("cp /tmp/100mb.zip /mnt/nfs/100mb.zip");

Die Laufzeit dieses Scripts ist nur 5 Sekunden! Ich muss also die Datei erstmal lokal auf die Festplatte schreiben, um sie dann mit dem System-Befehl „cp“ auf das NFS-Share zu kopieren.

Warum ist „cp“ so viel schneller als copy()? Ich hätte getippt dass PHP intern etwas ähnliches macht oder sogar das selbe? Oder ist die „cp“-Funktion deutlich im Vorteil weil sie den Filesystem-Cache oder Kernel-Cache oder ähnliches ausnutzen kann, was die copy()-Funktion nicht tut? Oder liegt es daran dass sowohl file_put_contents() als auch copy() intern immer in kleinen Häppchen vorgeht: „4KB lesen, 4KB schreiben, 4KB lesen, 4KB schreiben…“, und dass das sehr unperformant für eine NFS-Verbindung ist?

Kann mir das jemand erklären? Warum ist PHP so schlecht darin eine Datei auf ein NFS-Share zu kopieren?

Ich nutze in diesem Fall PHP 5.5.9-1ubuntu4.6

Ich bin dankbar über jeden Ratschlag.



Keine ähnlichen Artikel.

php linux copy copy-langsam copy-nfs-share cp file-put-contents
Weitere News:
Schreibe einen Kommentar:
Themen:
file-put-contents cp copy-nfs-share copy-langsam copy linux php
Entweder einloggen... ...oder ohne Wartezeit registrieren
Benutzername
Passwort
Passwort wiederholen
E-Mail