mmofacts.com

"Nicht-Thread-Sichere" Skripte in PHP

gepostet vor 19 Jahre, 5 Monate von Teonas
Servus,
mal eine Frage an Leute, die sich mit PHP auskennen:

Bei JSPs (Java Server Pages) gibt es eine Möglichkeit, Seiten/Servlets als "Not thread save" zu markieren. Damit gibt es immer nur eine Instanz dieser Seite/dieses Servlets in einem JSP-Container. Das bringt insbesondere bei Datenbank-Stress Vorteile, da die Servlet-Engine weniger (parallele) Requests auf die DB generiert (Interessierte siehe hier: http://rubis.objectweb.org/download/Middleware-2003.pdf).

Jetzt die Frage: Kann man so etwas auch mit einem PHP-Modul erreichen? Da die Schreiber o.g. Papers das nicht untersuchen, muss ich annehmen nein, jedoch interessierts mich doch, ob einer vielleicht mehr.

Grüße
Teonas
gepostet vor 19 Jahre, 5 Monate von TheUndeadable
Du kannst mit Hilfe von File-Locking ne threadsichere Umgebung aufbauen
gepostet vor 19 Jahre, 5 Monate von Teonas
Das scheint es grundsätzlich zu tun.

Disk-IOs zählen jetzt nicht zu den schnellsten Dingen. Hat jemand Erfahrung, wie sich das auf die Performanz auswirkt? IMO gehts zumindest bei Unix direkt an das Betriebssystem, da hier der identische Befehl existiert.

Eine weitere Geschichte ist unter Unix, dass ein anderer Prozess wohl in der Lage ist, sich über die Locks hinweg zu setzen (zumindest wie ich hier lese). Eine HTML-Version der Manpage von flock auch hier (Siehe Abschnitt Notes). Grundsätzlich könnte sich also ein anderer Apache-Prozess über das Lock hinweg setzen.
gepostet vor 19 Jahre, 5 Monate von Gambler
Du kannst auch die Datenbank locken. Bei MySQL leider nur ganze Tabellen aber bei PostgreSQL kannst du soweit ich weiss einzelne Zeilen sperren.
gepostet vor 19 Jahre, 5 Monate von Teonas
Das DB-Locking bzw. Lock-Kollisionen versuche ich ja gerade zu umgehen, da, wie du in dem Middleware-2003-Paper lesen kannst, es erhebliche Performancegewinne unter Stress bringt, das Ganze in der Applikation zu erledigen.

Postgres kann Row-Level-Locking, genauso wie die InnoDB-Tabellen von MySQL, richtig, beide sind aber deutlich langsamer als eine MyISAM-Tabelle trotz Table-Level-Locking. Deshalb ist es aus Performancegründen nicht so ratsam, den Typ zu wechseln. IMO bringt es mehr, die Tabelle intelligent anzusprechen, den Lock-Kollisionsfall selten eintreten zu lassen.
gepostet vor 19 Jahre, 5 Monate von KEEN
Original von TheUndeadable
Du kannst mit Hilfe von File-Locking ne threadsichere Umgebung aufbauen


Probleme bekommt man dann aber, wenn man mehrere Webserver parallel einsetzen will/muss. In dem Fall kommt man um einen Datenbank lock nicht drum herum.
gepostet vor 19 Jahre, 5 Monate von Teonas
Auch das sollte klar sein. Was ich unterbinden will, ist das mehrere Server mit JEWEILS mehreren Threads auf einer DB (und der gleichen Tabelle) mit aufwendigen Operationen herumorgeln und dabei Lock-Kollisionen verursachen.

Dass 5 Server gleichzeitig auf einer DB Kollisionen produzieren, kann ich nur noch mit einem globalen Kontext lösen. Den muss ich dann aber AFAIK selbst programmieren (bevor Wünsche kommen: NEIN! ;-) ).
gepostet vor 19 Jahre, 5 Monate von schokofreak
Das Zauberwort heist Gegenseitiger Ausschluss (Mutual Exclusion oder so).
Dazu gibt es mehrere möglicher Konstrukte, mit denen man das erreichen kann.

Semaphoren / Mutexe sind am geläufigsten:
- Semaphor: Zähler so und so viele dürfen maximal z.B. auf DB zugreiffen
- Mutex: "Binärer Semaphor" maximal einer darf auf die DB zugreiffen

Es gibt je nach Platform ne vielzahl weiterer, vortgeschrittener Konstrukte. Beispielsweise solche, welche im User- Space funktionieren (und so wechsel in Kernel minimieren / extren Leisung einsparen) oder solche welche acuh Netzwerk- Tauglich sind.

In der Windows Welt könnt ich dir jetzt ohne weiteres sagen, dass du den Mutex sucht. Windows Mutexe kann man auch über ein Netzwerk hinweg betreiben.
Für die Unix welt kann ich dir leider nichts sagen. Must halt (unter all den oben erwähnten Schlagworten) googeln gehen.

Für den Fall dass du nichts findest. Auf KEINEN FALL selber entwickeln. Da schmeisst du nur jehnstes an rechenleistung / Stabilität / Sicherheit weg.

Falls du nichts findest: Einen Share öffnen. Dort das von TuD geliebte File- Locking verwenden. Excessiv testen.
File- Locking ist nicht extrem rechenaufwendig (auf jeden fall weniger als eine selbst gestrickte Lösung welche doch nicht funktioniert).

Und wenn du auch das nicht willst: Nimm doch eine "Hard- Core Variante"?
- Jeder Client besitzt einen Client Side Mutex (wie gesagt weiss nicht ob man die Unix auch in Netzwerk Modus betreiben kann).
- Fazit: Jetzt können maximal so viele Connections zur DB existieren, wie Clients existieren.
- Nun wird DB MaxConnection auf 1 gestellt
- hat der Client n Mutex, und MaxConnection ist auf 1, so macht er einen CSMA/CD angelehnten Algo durch.

Gruss
gepostet vor 19 Jahre, 5 Monate von schokofreak
Nachtrag:
In meinen Augen sollte man sowas auf KEINEN Fall direkt in PHP lösen. Was wenn ein Script abschmiert?

Die sauberste lösung wär ein TCP Server in C++. Dieser empfängt connections. Client macht ein blokierendes Read
Sobald der Server dem Client ein Token gibt (etwas schreibt) wird das Bloking Read wieder aktiv...
Das Script läuft ab.
Ende des scriptes schliesst der Client die TCP / Connection SAUBER (der Server merkt dies und kann nun neues Token vergeben).

ist natürlich zentral gesteuert mit all seinen Nachteilen und hoher Latenzzeit.

Gruss
gepostet vor 19 Jahre, 5 Monate von Teonas

Für den Fall dass du nichts findest. Auf KEINEN FALL selber entwickeln. Da schmeisst du nur jehnstes an rechenleistung / Stabilität / Sicherheit weg.


Hatte ich das nicht schon deutlich verneint...? ;-)

Das mit dem TCP ist aber eine Idee, muss aber nicht in C sein, denn:
Ich will ja nicht den Server an sich beschränken (DB-Connections = 1), damit kann er ja auch nur eine Verbindung zum Lesen / parallelen Schreiben auf die DB öffnen (inperformant - parallel könnten ja andere Tabellen gelesen/geschrieben werden).

Man könnte aber ein globales Objekt im Container erstellen, das wie ein "Pool" mit einer Connection funktioniert. Damit kann man mehrere Skripte dazu zwingen, eine Verbindung für eine Tabelle zu nutzen, ohne alle anderen zu blockieren. Ein weiteres Skript bekommt die Conn. nur dann, wenn die Verbindung frei ist.

Problematisch finde ich nur, dass flock() schönes Queing macht, das man bei o. beschriebener Lösung selbst implementieren müsste. Allerdings könnte man auch die Connections erhöhen (vielleicht macht Faktor 2 noch keine oder kaum Kollisionen) und so im Zweifelsfall noch etwas Performance raus holen.

Das klingt mir alles zwar noch etwas dreckig, ich poste aber mal wenn mir was sauberes enfällt.
gepostet vor 19 Jahre, 5 Monate von schokofreak
dann bau n PHP TCP Server... welcher von der Konsole aus gestartet wird?
Geht auch ganz einfach, und ist äusserst speditiv.
einfach aufpassen, dass der Server mitkriegt ob eine Verbindung wirklich noch offen ist oder nicht; dann klappt das schon!

Gruss
gepostet vor 19 Jahre, 5 Monate von Teonas
Ich wollte jetzt keinen Serverprozess machen, sondern ein globales PHP-Objekt. Inter-Prozess-Kommunikation erscheint mir gar nicht notwendig.

Aber vielleicht mal ein Fazit: Alles etwas komplizizert mit PHP, bei JSPs eine Zeile (thread-safe=false). Schade, dass die nur mit Root-Servern einsetzbar sind. Sonst würden sie vielleicht weitere Verbreitung finden - oder setzt die gar schon einer ein?
gepostet vor 19 Jahre, 5 Monate von Kampfhoernchen
Ich hab alle 3 wichtigen Web-Technologien schon ausprobiert. weil ich sehen wollte, was schneller ist, was schöneren Code prodziert usw

Ergebnis:
1. ASP.NET (mit C++)
2. PHP
3. JSP (Sehr langsam beim Zusammenbau von komplexen Seiten, dafür schneller bei größeren Berechnungen)

Ich hab mich dann für PHP entschieden, weil ASP.NET unter Linux-Servern nicht wirklich stabil läuft. Ich denke mal, das die LAMP immer noch die beste Lösung ist, wenn man es nicht grade mit einem C++-Programm vergleicht, das direkt an Port 80 lauscht (hatten wir hier ja auch schonmal irgendwo).
gepostet vor 19 Jahre, 5 Monate von Teonas
Dazu mal ein paar Detailfragen:

1. War bei dem Vergleich der Technologien PHP nackt oder mit Speedups versehen wie eAccelerator (der momentan nicht stabil ist) ?

2. Hast du bei JSPs spezielle Features wie Memory-Sessions genommen oder auch alles in die DB geschrieben?

3. Lief der JSP-Container als Apache-Modul oder als separater Server-Prozess? Letzteres wäre deutlich schneller.

Noch was generelleres:
Deine Kommentare gehen bei JSPs auf die Performance ein, im Aufriss erwähnst du aber auch Code-Qualität und vermutlich Wartbarbeit. Gilt deine Wertung auch analog für diese Betrachtung?
gepostet vor 19 Jahre, 5 Monate von Kampfhoernchen

1. War bei dem Vergleich der Technologien PHP nackt oder mit Speedups versehen wie eAccelerator (der momentan nicht stabil ist) ?

Zend Optimizer und vorcompiliertes PHP


2. Hast du bei JSPs spezielle Features wie Memory-Sessions genommen oder auch alles in die DB geschrieben?

Datenbank (MySQL)


3. Lief der JSP-Container als Apache-Modul oder als separater Server-Prozess? Letzteres wäre deutlich schneller.

sep. Server-Prozess, als Modul hab ichs nicht zum laufen bekommen (Apache abgeschmiert, warum hab ich nicht rausfinden können)


Noch was generelleres:
Deine Kommentare gehen bei JSPs auf die Performance ein, im Aufriss erwähnst du aber auch Code-Qualität und vermutlich Wartbarbeit. Gilt deine Wertung auch analog für diese Betrachtung?


Bei vernünftiger Programmierung waren da eigentlich alle 3 gleichauf, JSP hat vielleicht den Vorteil, dass es sehr viele Java-Tools gibt, die man auch für JSP verwenden kann. Bei PHP muss man halt aufpassen, dass man die OO konsequent durchzieht, besonders Trennung von Anzeigen-, Applikations- und Datenlogik, sonst kann der Code schnell unübersichtlich werden. Für C gelten halt die üblichen Stärken / Schwächen.
gepostet vor 19 Jahre, 5 Monate von Teonas
Noch ein paar Fragen wären für die Bewertung deines Vergleichs interessant:

Da du es mit einem Apache-Modul versucht hast, sollte es wohl für die JSPs ein Tomcat gewesen sein. Welche Version hast du denn da verwendet? Die 5er sind noch mal eine gute Menge schneller geworden als der 4.1.

Und dann würde mich so eine große Quantifizierung deiner Vergleichswerte in Bezug auf die Geschwindigkeit mal interessieren, wenn du da noch etwas genaueres weißt.
gepostet vor 19 Jahre, 5 Monate von Kampfhoernchen
Puh, das weiß ich nicht mehr, is ca. n halbes Jahr her. Aber ich denke, es war noch 4.1 oder schon ne Beta von 5, jedenfalls damals die aktuellste Version.

Die genauen Zahlen hab ich nicht mehr im Kopf, aber die Abstände lagen so bei 10-20 %. Getestet hab ich das ganze mit 50 oder 100 (weiß nicht mehr so genau) Requests, die ich verteilt auf 1 Sekunde abgesetzt habe, und hab die Antwortzeiten gemessen.
ASP war mit "Abstand" (wenn man bei ms von Abstand reden kann), am schnellsten mit allen Requests fertig, hier hat JSP verloren (wohl weils ziemlich speicherintensiv ist, da man sehr viele Objekte anlegen muss, bevor da überhaupt was geht).
Beim 1. Request war PHP am langsamsten (doppelt so lange, keine Ahnung wieso), hier war JSP am schnellsten.
Im Durchschnitt hat ASP den niedrigsten Durchschnitt, während sich PHP und JSP nicht sehr viel gegeben haben, aber PHP doch ein wenig schneller war.

Hier noch mein Test-Szenario:
P4 2,533 GHz, 512 MB RAM (Geschwindigkeit weiß ich net mehr, hab inzwischen nen 1024iger drin), Platte mit 7200 RPM, WIN XP Pro, alle unnötigen Prozesse gekillt.
Einmal hab ich eine Tabelle aus einer Datenbank , dann wurden 2 Dateien geladen und zeichenweise vermischt und zum abschluss hab ich ihn einige mathematische Funktionen berechnen lassen (Wurzeln, große Zahlen, Hamming-Distanz zwischen 2 Zeichen ect.)

Beim letzteren war JSP übrigens am schnellsten, bei Datenbanken ASP.NET (mit MS SQL-SERVER (für studenten kostenlos)) und bei den Zeichenoperationen PHP. Dann hab ich noch ASP.NET mit MySQL ausprobiert, was das Ergebnis zwar verschlechtert hat, aber ASP Trotzdem noch schneller war.

Die Requests hab ich immer abwechselnd abgesetzt.
gepostet vor 19 Jahre, 5 Monate von woodworker
Original von Teonas
Ich wollte jetzt keinen Serverprozess machen, sondern ein globales PHP-Objekt. Inter-Prozess-Kommunikation erscheint mir gar nicht notwendig.


dem kommt glaube ich SRM am nähsten
http://www.vl-srm.net/
gepostet vor 19 Jahre, 5 Monate von TheUndeadable
Von SRM finde ich persönlich die Dokumentation sehr dürftig.
gepostet vor 19 Jahre, 5 Monate von woodworker
ist sie auch aber wenn man einmal hinter gestiegen ist ist es verdamt geil

verdamt ungeil ist im moment halt nur das sie noch keine php5 support haben.
gepostet vor 19 Jahre, 5 Monate von Teonas
Irgend wie gefällt mir dieses Zitat aus der Doku nicht:
What you will need


* Patience
* ...
Sie könnten daraus mal ein etwas zentraler angesiedeltes Projekt machen (Sourceforge, Berlios, vielleicht auch eine OS-PHP-Community), vielleicht würde es dann mal stable. Normalerweise verwende ich zum ruhig Schlafen nichts was nicht stabil ist.
gepostet vor 19 Jahre, 5 Monate von woodworker
naja ich auch nicht

nur es gibt halt eine unterschiedliche auffassungs gabe von stable

ich kenne debian woody pakete die warn als ich das letze mal debian genutzt habe nicht wirklich stabil und ich nutze auf Gentoo Linux jede menge "unstable" pakete die keine probleme machen

Auf diese Diskussion antworten