Mailinglisten-Archive |
> > [...] Ich glaube, du solltest mal einen meiner Blogartikel lesen: > > http://www.grobmeier.de/2009/08/21/performance-ofnonblocking-write-to-files-via-php.html > > Naja, den dortigen Vorschlag > > $fp = fopen($file, 'a+'); > flock($fp, LOCK_UN); > while($count < $loop) { > if (flock($fp, LOCK_EX)) { > fwrite($fp, $text); > } > flock($fp, LOCK_UN); > } > fclose($fp); > > halte ich erstens für umständlich (wenn die Schreibzugriffe hinterein- > ander erfolgen, warum nicht einmal sperren, dann alles schreiben, dann > entsperren?) weil du unter umständen ja auch zwischendurch was anderes von anderen threads rausschreiben willst, ohne diese Ordnung einzuhalten (z.b. im Falle logging). > und zweitens für fehlerträchtig (was ist, wenn ein zweiter > Prozess eine Zeile anhängt, aber der Dateizeiger des ersten Prozesses > noch eine Zeile darüber steht und selbst eine Zeile schreiben will?). flock wartet in dem fall, bis es einen lock erhält. erst dann liefert es true zurück und läuft weiter > Ohne das wiederholte Entsperren und Sperren ist das ja meiner ursprüng- > lichen Anfrage ähnlich (bis auf ftruncate($fp, 0);), und mir ging es > ja weniger um die Geschwindigkeitsdetails als vielmehr um das Sperren > an sich. http://php.net/manual/de/function.flock.php "flock() erlaubt es Ihnen ein einfaches Leser/Schreiber Modell zu erstellen, welches auf fast jeder Plattform benutzt werden kann" Gruß, Christian > > > Am 16.03.2010 21:52 schrieb Dieter Schmidt: > > > damit du nicht herumstochern musst, kann ich dir nur eines empfehlen, > > gehe der Sache wirklich auf den Grund. Ich würde an deiner Stelle eine > > Profiler installieren. [...] > > Nett gemeint, aber ich glaube, das kann ich als Kunde eines Webhosting- > Anbieters nicht. Außerdem hat mich schon die Produktbeschreibung er- > schlagen -- bis ich das kapiere, habe ich durch ein paar gut durch- > dachte Änderungen vielleicht schon mehr gewonnen... > > > Am 17.03.2010 20:48 schrieb Yannik Hampe: > >> [...] der schlafende Prozess hält noch Systemressourcen, wie zum >> Beispiel Filelocks. Das kann andere Prozesse wiederrum blockieren. > > Ja, das ist meine Vermutung (leider nicht mehr als eine Vermutung). > >> [...] Wie viele Prozesse sammeln sich denn da an? 5? 10? 100? 1000? >> Irgendwann werden auch schlafende Prozesse für das System zu Last, >> wenn es nur genug sind. [...] > > Größenordnung bis zu 50 würde ich sagen. > >> Dateisperren werden auch dann freigegen, wenn man fclose() aufruft. >> fclose() wird am Ende jedes Scripts von php für alle noch nicht >> freigegeben Dateien automatisch aufgerufen. > > Gilt das auch für Skripte, die per Timeout beendet werden? > >> [...] Bedenke hier, das ftruncate() die Datei auf 0 Byte kürzt. Der >> Dateipointer, der sich am Ende der Datei befindet bleibt von >> ftruncate jedoch unberührt. Da du jedoch mit fputs wohl an den >> Anfang der Datei schreiben möchtest, solltest du einmal rewind($fp); >> ausführen. > > Ok, verstanden. Guter Tipp! > >> [...] Und ja, für Dateien zum lesen musst du auch sperren, aber dann >> brauchst du keine exklusive Sperren, dann tut flock($fp, LOCK_SH). > > Ja, das hatte ich auch so verstanden und gemeint. Danke für die Be- > stätigung. > >> [...] Bei file_put_content kannst du einen Parameter zum Sperren >> mitgeben: file_put_contents("/some/path", "some data", LOCK_EX); >> Leider habe ich keine Ahnung, wie file_get_contents intern >> funktioniert und die Leute die sich in Foren dazu auslassen >> spekulieren alle nur und haben keine Ahnung ;-). [...] > > Ok, dann werde ich auch die durch fopen() usw. ersetzen. > >> Woher weißt du denn, dass der Server hängt? > > Eine Suchanfrage (bei der vermutlich eine der Index-Dateien neu auf- > gebaut werden muss, s. o.) führt zum "halben" Laden der Seite (eben > bis zu der Ausgabe vor Neuaufbau der Index-Datei) und macht danach > nicht weiter (keine weitere HTML-Ausgabe, Browser zeigt weiter "Lade > Seite..." an). Vermutung: Prozess wartet "ewig" auf Freigabe zum > Schreiben der Index-Datei. > >> Was ist das überhaupt für ein Server? Linux? > > Webhosting auf Linux-Server (x86_64). > >> Hast du ssh-Zugang drauf? > > Öh... Was ist das? > >> Meinst du er hängt, weil in deinem Browser nichts ankommt? > > So in etwa, s. o. > >> Oder weil du auf einer Konsole warst und gesehen hast, dass der >> Prozessor auf 100% Auslastung steht? > > Nein, den Server bringe ich nicht in die Knie (zum Glück -- mit End- > losschleifen habe ich das schon hinbekommen...). > >> [...] Untersuchen könntest du das in dem du alle deine flock-Aufrufe >> durch so etwas erstzt: >> flock($fp, LOCK_EX | LOCK_NB, $wouldblock); >> if ($wouldblock) throw new Exception('Could not acquire lock for file ...'); > > Naja, es soll ja durchaus zulässig sein, dass ein Prozess warten muss, > bis er an die Reihe kommt. > >> Eine weitere Möglichkeit zur Fehlersuche sind debugger. [...] in dem >> du die entsprechende option in der php.ini [...] Dann spuckt dir >> xdebug bei jeder Anfrage eine Datei aus (in das ebenfalls in der >> php.ini eingestellte Verzeichnis. Normalerweise /tmp) [...] > > Ich weiß nicht, ob ich a) die nötigen Zugriffsrechte dafür habe und > b) verstehe, was mir der Debugger mitteilt. > >> [...] Wenn der Fehler nur bei jedem hundertsten Aufruf zum Fehler >> führt, dann ist das allerdings doch ein sehr frustrierende >> Angelegenheit. Genau wie die Methode mit dem profiler [...] > > Und so in etwa dürfte es sein, vielleicht ist die Zahl sogar noch > größer. > > > Alles in allem gab es ja das eine oder andere ermutigende Wort, die > flock()-Funktion so einzusetzen, wie ich das vorhatte (nun ergänzt um > die rewind()-Funktion). Daran werde ich mich nun begeben. > > Außerdem hatte ich noch eine andere Idee: Da ich (aus purer Faulheit, > eine Funktion zu entwickeln, die nach Änderung im Datenbestand die > bestehende Index-Datei an der richtigen Stelle geraderückt) bei Daten- > änderung die Index-Datei verwerfe und bei der nächsten Suchanfrage neu > aufbaue, kann es bisher zu folgender Situation kommen: Anfrage A löst > Neuaufbau aus und sperrt währenddessen die Index-Datei, Anfrage B > stellt ebenfalls fest, dass die Index-Datei neu aufgebaut werden muss > und wartet auf Freigabe der Sperre -- um dann die Index-Datei eben- > falls neu aufzubauen. Währenddessen kommt Anfrage C usw. Ich kann mir > vorstellen, dass dieses wenig durchdachte Prinzip zu einem Dateisperre- > Stau führen kann und habe es nun dahingehend abgewandelt, dass nach > Erhalt der Sperre die Bedingung für Neuaufbau nochmals überprüft wird. > Falls der Index gerade neu erzeugt wurde und keine Änderung in der > Zwischenzeit den Index als überholt deklassiert, biege ich vor > ftruncate() wieder ab, baue die Index-Datei nicht wieder auf und gebe > die Sperre gleich wieder frei. > > Mal schauen, ob es mit diesen Änderungen besser wird. > > Eine Frage bleibt für mich aber trotzdem offen: Wieso hat es bei dem > oben beschriebenen "Hängenbleiben" nicht geholfen, die Seite neu zu > laden, wenn es geholfen hat, erst das Session-Cookie im Browser zu > löschen und dann die Seite neu zu laden? Teilt mir der Server keinen > neuen Prozess zu, wenn er über die Session-ID feststellt, dass ich > schon einen Prozess (oder mehrere) laufen habe? Ich kann mir nicht > vorstellen, dass den Server die Session-IDs interessieren, aber woran > kann es sonst liegen? > > Nochmals vielen Dank an alle, die mir geantwortet haben! > > Mario Haßler > -- > ** Allgemeine deutschsprachige PHP-Liste: php at phpbar.de ** > Informationen: http://www.phpbar.de > http://lists.phpbar.de/mailman/listinfo/php >
php::bar PHP Wiki - Listenarchive