phpbar.de logo

Mailinglisten-Archive

[php] =?iso-8859-1?Q?Re:_=5Bphp=5D_Re:_=5Bphp=5D_Chat-=D6konomie?=

[php] =?iso-8859-1?Q?Re:_=5Bphp=5D_Re:_=5Bphp=5D_Chat-=D6konomie?=

Till Gerken till_(at)_phpwebdev.com
Thu, 15 Jun 2000 22:33:26 +0200


> Mist, hatte ich erwähnt, daß ich Psychologe mit Programmierkenntnissen
> bin, und nicht Informatiker? :) Was meinst du mit Inner-Loop? Die
> Endlosschleife, die die Datenbankabfragen zur Ausgabe macht?

Für dieses Beispiel hast Du recht.

Der Inner-Loop ist die innerste Schleife im Programm (besser läßt es sich
leider nicht erklären), was dort genau gemacht wird, hängt vom Programm ab:

Z.B.:

do_setup();
while(!$done)
{
  while(!$read_msg)
  {
     // innerste Schleife, "Inner Loop"
  }
}
do_deinit();

Bei einem Chatsystem würde dort in der Regel die Datenbankabfrage nach neuen
Nachrichten stattfinden.

> Und wonach richtet sich die Länge des sleep()?

Die Länge des sleep() bestimmt die Latenz (praktisch die Reaktionszeit) des
Programms. Je länger der Prozeß "schläft" (also toter Mann spielt), desto
länger dauert es, bis er wieder auf eine Nachricht reagieren kann.

Beispiel:

Der Prozeß fragt die Datenbank ab, legt sich dann für 10 Sekunden schlafen,
fragt die Datenbank erneut ab, legt sich wieder für 10 Sekunden schlafen
usw.

Ein Benutzer, der direkt nach der Abfrage eine Nachricht eingeben würde,
müßte dann theoretisch maximal 10 Sekunden warten, bis er seine Nachricht
auch auf dem Schirm sehen würde. Durch die statistische Verteilung wäre also
die durchschnittliche Wartezeit bei 5 Sekunden pro Nachricht, welche aus
ergonomischen Gründen sehr lang ist (das müßtest Du als Psychologe am besten
beurteilen können :) )

Der Standardwert bei phpChat liegt bei zwei Abfragen pro Sekunde, wodurch
eine maximale Reaktionszeit von 0.5 Sekunden und eine durchschnittliche
Reaktionszeit von 0.25 Sekunden anfällt. Diese Reaktionszeit ist garantiert,
alles andere liegt dann nur noch an der Netzwerklast.

> Und, erkaufe ich mir die Senkung der Prozessorlast nicht mit höherem
> Speicherbedarf? Sowas um die 2,5 MB / Client?

Nein, die Senkung der Prozessorlast ist völlig unabhängig vom
Speicherverbrauch (außer, Du forderst vor dem sleep() enorm viel Speicher an
und gibst ihn erst hinterher wieder frei).

> Vielen Dank schon mal für deine Antwort, aber wenn mir jemand noch was
> zur konkreten PHP-Umsetzung sagen könnte, oder auf ein Tutorial o.ä.
> verweisen könnte, dann erspart mir das locker 2 Wochen intermittierender
> Testerei über Trial & Error, einer unter Nicht-Informatikern sehr
> beliebten Programmiertechnik.

Unter http://www.phpwizard.net/phpChat kannst Du Dir phpChat herunterladen.
Vor allen Dingen von Interesse dürften dabei für Dich chat_login.php3,
chat_submit.php3 und configure.inc.php3 sein, diese zeigen schonmal die
Grundlage für Interprozeßkommunikation mittels Semaphoren und Shared Memory.

Die volle Dröhnung gibts in chat_bot.php3, ist aber etwas schwieriger zu
verstehen, weil dort auch das ganze IRC-Handling mit drin ist.

> $shm_key = shm_attach($key);  // und wo kriege ich $key her?

Der Key ist frei zu wählen, muß einmalig im System sein und gleich für jeden
Prozeß, der auf dasselbe Segment zugreifen will. Sonst auch über die
Session-ID zu lösen, allerdings muß man dann für jeden Client ein neues
Segment anlegen, was Speicherverschwendung ist.

> // irgendwo gibt es eine Eingaberoutine
> if($neue_nachricht != "")  // jemand chattet
> {
>   $chat_flag = 1;
>   shm_put_var($shm_key, $key_chat_flag, $chat_flag);
> }

Da jeder Prozeß auf dasselbe Segment zugreift, müssen im Segment mehrere
Flags untergebracht werden - deswegen bietet sich die Speicherung über ein
Array an.

> // und irgendwo schaut irgendwer nach Neuigkeiten
> if(shm_get_var($shm_key, $key_chat_flag == 1) )
> {
>   // löse MySQL-Abrage-Routine aus
> }

Vom Gedankengang her richtig, von der Implementation nicht, aber das ist mit
Manual und Beispiel leicht zu korrigieren. :)

> // und wenn keiner mehr da ist:
> shm_detach($shm_key);  // trennen
> shm_remove($shm_key);  // speicher freigeben

Auch korrekt.

> Und wofür sind jetzt die Semaphoren?

Die Semaphoren werden aus folgendem Grund benötigt:

In Mehrprozeßsystem laufen alle Prozesse gleichzeitig, d.h. während z.B.
einer Deiner Chatprozesse gerade eine Nachricht empfängt und dies im Shared
Memory bekannt geben will, könnte ein anderer Chatprozeß, der ebenfalls
gerade eine Nachricht empfangen hat, den ersten Prozeß unterbrechen. Der
zweite Prozeß würde ebenfalls eine Veränderung im Shared Memory vornehmen,
jedoch beide Prozesse würden nichts von den Veränderungen des jeweils
anderen Prozesses wissen. Der später wieder reaktivierte erste Prozeß würde
also die Änderungen des zweiten Prozesses überschreiben, wodurch Inkonsisten
im Shared-Memory-Segment entstehen.

Aus diesem Grund benutzt phpChat die Semaphoren. Semaphoren sind eine Art
"globale Zähler". Jeder Prozeß kann eine Semaphore anfordern und wieder
freigeben. Wird eine Semaphore angefordert, dann wird ihr Wert erhöht. Wird
sie freigegeben, wird ihr Wert erniedrigt. Nur wenn der Wert der Semaphore
auf 0 ist, ist sie "frei".

Wenn also ein Prozeß eine Änderung am Shared Memory vornehmen will, fordert
er dafür vorher eine Semaphore an. Ein eventuell den ersten Prozeß
unterbrechender zweiter Prozeß, der ebenfalls Änderungen am Shared Memory
vornehmen würde, würde ebenfalls die Semaphore anfordern, welche jedoch dann
bereits schon durch den ersten Prozeß "geblockt" ist. Dadurch wird der
zweite Prozeß automatisch wieder schlafen gelegt, bis der erste Prozeß die
Semaphore wieder freigegeben hat.

Dadurch lassen sich die obengenannten Inkonsistenzen ausschließen.

Till




php::bar PHP Wiki   -   Listenarchive