![]() Mailinglisten-Archive |
Thomas Koudela wrote: > Hi. > > > Ein schlafender Prozess ist ein Programm, welches auf seinen Einsatz > wartet. Damit es in dieser Zeit keine Rechenleistung verschleudert > schl�ft es im Arbeitsspeicher. Ein schlafender Prozess d�rfte IMHO keine > Zugriffsrechte blockieren - es sei denn die Programmierer haben Mist > gebaut. Es sei denn der schlafende Prozess h�lt noch Systemressourcen, wie zum Beispiel Filelocks. Das kann andere Prozesse wiederrum blockieren. Wie Christian schon erkl�rt hat, k�nnte es sich um das normale pooling von Prozessen deines Webservers handeln. Muss aber nicht. 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. Schlie�lich muss das System auch alle im Auge behalten und Prozesse wenn n�tig weiter laufen lassen. > >> Ein Problem k�nnte darin liegen, dass die Suche manche Bereiche der >> Seite "indiziert", d. h. eine Art Zusammenfassung erstellt und diese >> speichert. (Wenn sich bis zur n�chsten Suche nichts �ndert, kann die >> Zusammenfassung wiederverwendet werden und spart dann Zeit.) Bei den >> Dateioperationen benutze ich die flock()-Funktion in ihrer Reinform, >> auch wenn mir bewusst ist, dass ein fopen(..., 'w') nicht wirklich dazu >> passt. Um das Thema "Abbruch durch den Benutzer" habe ich mich bisher >> noch nicht gek�mmert. Kann es also sein, dass ein Abbruch nach flock() >> die folgenden Prozesse ausbremst, die sich mit flock() auf die gleiche >> Datei beziehen? Kann ich das mit ignore_user_abort() in geordnete >> Bahnen lenken? > > Nat�rlich ist ein Script-Abbruch bei gesperrten Datei ziemlich fatal, > wenn keine Vorkehrungen zur Entsperrung im Fehlerfall getroffen wurden. > Sinnvoll w�re, wenn PHP beim Schlie�en der Datei oder sp�testens nach > Ende des Scriptes alle noch gesperrten Dateien automatisch entsperrt. > Ich wei� allerdings nicht, ob die PHP-Entwickler so etwas implementiert > haben. Ich w�rde eine Datenbankl�sung vorziehen, zumal Du dann mehrere > Indizierungen speichern k�nntest und absolut sicher w�rst, dass die > Implementierung auf jedem System gleich gehandhabt wird. Wenn Du die > Datenbank intelligent nutzt, m�sstest Du in Deinem Fall auch auf den > Lock verzichten k�nnen. 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. > >> Dann zu flock(): http://www.php.net/manual/de/function.flock.php >> bietet in den Benutzerkommentaren viele Anregungen, wie man aus dem >> etwas ungeschickten Ansatz, den Zugriff erst nach �ffnen zu sperren, >> etwas Brauchbares macht. Ist >> >> $fp = fopen(..., 'a'); // <- Dateiinhalt erst bewahren >> flock($fp, LOCK_EX); >> ftruncate($fp, 0); // <- jetzt erst l�schen >> fputs($fp, ...); 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. >> flock($fp, LOCK_UN); >> fclose($fp); >> >> der "richtige" Ansatz als Ersatz f�r fopen(..., 'w') + flock()? Sehe >> ich das richtig, dass auch fopen(..., 'r') mit flock() kombiniert >> werden muss, damit das Konzept stimmig ist? Sieht f�r mich gut aus :-). Und ja, f�r Dateien zum lesen musst du auch sperren, aber dann brauchst du keine exklusive Sperren, dann tut flock($fp, LOCK_SH). >> Und was ist mit Funktionen wie file_get_contents() / file_put_contents()? > > Bei file_get_contents() und file_put_contents() ist die dargestellte > Kombination mit flock() �berfl�ssig, da in einem Rutsch gelesen bzw. > geschrieben wird. Eigentlich bezweifle ich, dass das dargestellte > �berhaupt Sinn macht, denn sobald eine Datei zum Schreiben ge�ffnet > wird, m�sste automatisch auf Betriebssystemebene, die Datei f�r andere > Prozesse gesperrt sein, bzw. warten bis nicht mehr aus der Datei gelesen > wird. Sonst k�nnte es zu Konflikten zwischen unabh�ngigen Programmen > kommen! Konflikte kann ich mir nur bei Multi-Thread-Servern vorstellen, > welche den Zugriff auf eine externe Ressource intern vorverwalten. �hm... Nein. 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 ;-). Das w�re allerdings mal interessant, wenn es einer wei�... Raus damit! > >> F�r Hilfestellung jeder Art bin ich dankbar; auch Hinweise / Vermutun- >> gen, dass das Problem vielleicht ganz woanders liegt. Ach ja: Wenn der >> Server ganz zu h�ngen scheint, hilft es manchmal, das Session-Cookie >> im Browser zu l�schen und die Seite neu zu laden, dann geht's. (Wei� >> zwar nicht, ob das irgendetwas mit dem Problem zu tun hat, aber ich >> erw�hne es lieber mal.) Woher wei�t du denn, dass der Server h�ngt? Was ist das �berhaupt f�r ein Server? Linux? Hast du ssh-Zugang drauf? Meinst du er h�ngt, weil in deinem Browser nichts ankommt? Oder weil du auf einer Konsole warst und gesehen hast, dass der Prozessor auf 100% Auslastung steht? Wenn du es nur anhand der Ausgabe deines Browsers gesehen hast, dann ist es in der Tat eine recht gute Chance, dass ein Skript versucht eine Dateisperre zu bekommen aber am Versuch leider h�ngen bleibt. Grund k�nnte ein Deadlock sein. 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 ...'); (Allerdings nutzt dir diese M�glichkeit der Fehlersuche nur etwas, wenn du die Methode auch wirklich verstehst, da sie auch "Fehlalarme" liefern kann. Was du letztlich wissen willst ist wann ein Prozess wirklich langfirstig nicht in der Lage ist eine Datei zu sperren, aber diese Methode wird dir schon einen Fehler anzeigen, wenn es nur in einem Moment nicht geklappt hat. Du musst dann in der Lage sein dass zu trennen.) Eine weitere M�glichkeit zur Fehlersuche sind debugger. Ich verwende beispielsweise xdebug (auf Linuxsystemen �ber den Paketmanager mit `<Paketmanager> install php5-xdebug` meist schmerzfrei in wenigen Sekunden installiert). Xdebug ist auch mit einem profiler ausgestattet (danke Dieter, dass du mich daran erinnerst das zu erw�hnen :-)), den du aktivierst, in dem du die entsprechende option in der php.ini (gerne ausgelagert in einer anderen Datei, die neben der php.ini auch noch geparst wird) aktivierst (xdebug.profiler_enabled oder so ganz �hnlich. Ist recht sprechend). Dann spuckt dir xdebug bei jeder Anfrage eine Datei aus (in das ebenfalls in der php.ini eingestellte Verzeichnis. Normalerweise /tmp), die praktischerweise mit cachegrind kompatibel ist, so dass du die Datei mit irgendwelchen tollen Programmen �ffnen kannst, die dir tolle Graphiken dazu zeichenen, was dich nat�rlich nicht interessiert, schlie�lich willst du nur wissen, was der letzte Befehl war, den das Skript ausgef�hrt hat, damit du wei�t, wo es h�ngt ^^. Wie auch immer. Es gibt zum Beispiel das Programm KCachegrind, damit kannst du die generierten Dateien �ffnen und Baukl�tze staunen, was der alles tolles rausfinden kann (Laufzeiten jedes einzelnen Funktionsaufrufs, alles sch�n grafisch dargestellt,...) (au�erdem kannst du staunen, wie erheblich langsamer der Profiler deine Skripte macht und wie unintuitiv die Bedienung von KCachegrind ist, aber das ist ein anderes Thema). Du kannst xdebug allerdings auch einfach benutzen um deinen Code gezielt zeilenweise auszuf�hren. Mit ein kleines bi�chen Frustrationstoleranz kann man das alles in eclipse zum laufen bringen, so dass du super komfortabel dich da durch klicken kannst. Bis in irgend einer Zeile es nicht mehr weiter geht und du dann wei�t, wo du weiter forschen musst. Jaa... 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, denn dann musst du dir auch jede Menge Dateien ansehen, bis du eine Gefunden hast in der das Skript erfolgreich h�ngen geblieben ist. > > Unter den Beitr�gen zur Funktion flock() gibt es jemanden, der darauf > hinweist, dass er bei 20 Anfragen in der Sekunde auf einen exklusiven > Lock der Apache-Server 100% der CPU-Leistung auffra� ohne abzubrechen. > Er gibt zwar einen Workaround an, aber sp�testens da, w�re die > Entscheidung f�r eine Datenbankl�sung bei mir gefallen. flock ist ein Systemaufruf und Systemaufrufe sind verdammt teuer. Jepp. Das ganze haut so extrem rein, dass sich einige gro�e Seitenbetreiber �berlegt haben bei ihrem Bytecodecache den test deaktivieren, der pr�ft ob sich die Orginaldatei ge�ndert hat und daher neu kompiliert werden muss. Alleine dieser �bersprungene eine Test kann die Serverlast auf ein Bruchteil k�rzen. Nur weil er nicht anfragt, wann eine Datei das letzte mal ge�ndert wurde. Erstaunlich, nicht wahr? :-). Es sei �brigens an dieser Stelle nochmal auf den Kommentar, der bei flock in der Bediene steht (und mit einem gro�en roten Kasten und einem fetten Warnhinweis versehen ist) hingewiesen: "On some operating systems flock() is implemented at the process level. When using a multithreaded server API like ISAPI you may not be able to rely on flock() to protect files against other PHP scripts running in parallel threads of the same server instance!" Ich versuche schon seit l�ngerem herauszufinden, ob ich ein some OS habe. Das k�nnte ja dann doch recht interessant sein zu wissen auf welchen Server das ALLES DENN BACH RUNTERGEHT, wenn der Server auf threads setzt und nicht auf fork, was ja eigentlich auch viel schneller ist... Also wenn es einer auf der Liste hier wei�, w�re ein kleiner Hinweis dazu sicherlich sehr nett :-). > beste Gr��e, > Thomas > Yannik
php::bar PHP Wiki - Listenarchive