ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/docs/ev.pod
Revision: 1.13
Committed: Wed Jan 16 02:59:25 2008 UTC (18 years, 8 months ago) by root
Branch: MAIN
CVS Tags: HEAD
Changes since 1.12: +7 -0 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.12 =head1 EV - (noch) ein Event-Modell für Perl
2 root 1.1
3     =head1 Was?
4    
5     EV ist ein Perl-Modul, das Ereignisgesteuertes Programmieren
6 root 1.2 unterstützt. Darin unterscheidet es sich erst einmal nicht von anderen
7 root 1.1 dedizierten Modulen wie "Event" oder die in jedes Toolkit (Gtk, Tk etc.)
8     eingebaute Ereignisverarbeitung.
9    
10     EV ist des weiteren eine Schnittstelle zur "Libev"-Bibliothek, eine Art
11     Libevent-Klon, und erbt deshalb deren Features (worin sich EV nun von
12     einigen anderen Modulen unterscheidet):
13    
14     =over 4
15    
16 root 1.3 =item Korrektheit
17 root 1.1
18     Die meisten Ereignis-Bibliotheken funktionieren gut, solange nichts
19     unvorhergesehenes passiert.
20    
21 root 1.2 Die meisten versagen kläglich, wenn die Systemuhr verstellt wird
22     (Zeitsprünge): Aus einem 10s-Timeout können bei Tk (Event, Glib etc.)
23     problemlos mal Jahre werden, aus einem Tag wenige Sekunden. EV unterstützt
24 root 1.1 sowohl relative Timer ("wecke mich in 10 Minuten auf, egal ob ntpd die
25 root 1.2 Uhr ändert oder nicht) als auch absolute Timer ("wecke mich 2008-10-10
26 root 1.1 12:17:23.445 auf, egal wie lange das wirklich dauert" oder gar "wecke
27 root 1.2 mich zur nächsten Mitternacht auf"), was kein anderes mir bekanntes
28     Event-Modell unterstützt.
29 root 1.1
30     Registriert man bei Tk (Event::Lib, ...) zwei Watcher auf denselben
31     Filehandle, so kann einer davon verloren gehen (nicht notwendigerweise
32 root 1.2 immer der ältere oder neuere).
33 root 1.1
34 root 1.2 Stellt man bei Event die "richtigen" Prioritäten ein, kriegt man eine
35 root 1.1 stetig wachsende Event-Queue die nicht kleiner wird (was allerdings selten
36     in Out-Of-Memory-Situationen endet, denn Event wird vorher zu langsam).
37    
38 root 1.2 Das alles sind Kleinigkeiten - bis das Programm deshalb mal "hängt", 100%
39 root 1.1 Rechenzeit verbraucht oder gar sporadisch versagt.
40    
41 root 1.2 Außerdem haben viele Event-Modelle (Event, Glib, Tk...) ein von Perl
42 root 1.1 abweichendes Objektmodell: verliert man beim Event oder Glib die Referenz
43     auf den Watcher, so hat man bestenfalls ein Memory-Leak. Die EV-Watcher
44     bestehen genau so lange, wie Referenzen darauf zeigen wie jedes andere
45     Perl-Objekt auch.
46    
47     Fork ist ein ganz spezielles Problem: wenige Event-Bibliotheken
48 root 1.2 unterstützen es direkt, vor allem diejenigen, die Epoll, Kqueue
49     o.ä. benutzen, da diese Schnittstellen sehr fork-feindlich sind. EV
50     unterstützt fork indem es den Kernel-Zustand im Kindprozess automatisch
51 root 1.1 wiederherstellt, sofern es benutzt wird.
52    
53 root 1.3 =item Geschwindigkeit
54 root 1.1
55 root 1.2 EV benutzt "die richtigen" Algorithmen zur Verwaltung: Heaps für die
56     Verwaltung der Timer (keine lineare Liste oder ähnliches wie alle
57 root 1.1 anderen), Arrays, wenn es um viele Watcher geht, Listen, wenn es nur
58     wenige (meist einen) geht. Auch geht Libev nicht vor jedem Pollen alle
59     seine Watcher (Event, Glib, ...) durch um zu sehen ob sie noch alle da
60     sind.
61    
62     Dadurch skaliert EV nicht nur hervorragend in die Bereiche von
63     hunderttausenden Filehandles und Timern (falls man das braucht), sondern
64     ist auch mit wenigen davon sehr schnell (was mindstens genauso wichtig
65     ist).
66    
67 root 1.2 Auch die Perl-Schnittstelle selbst wurde geschrieben, um unnötige
68 root 1.1 Laufzeitkosten zu vermeiden: EV erzeugt einen Watcher immerhin 40 mal
69     schneller als Event und fast viermal so schnell wie Glib, womit EV +
70     AnyEvent immer noch schneller sind als "nacktes" Glib.
71    
72     Auch der Speicherverbrauch ist sehr gering: EV-Watcher sind schlichte
73     geblesste Strings die den Libev-Watcher enthalten. Diese wiederum sind im
74     Vergleich mit anderen Bibliotheken recht klein (weniger als 100 Bytes).
75    
76 root 1.3 =item Skalierbarkeit
77 root 1.1
78     Nicht nur die Algorithmen, auch die Schnittstelle zum Betriebssystem muss
79     skalierbar sein, und das bedeutet leider auch: nicht portabel. Jedes
80     Betriebssystem braucht sein eigenes Rezept und daher auch sein eigenes
81 root 1.2 Backend: Libev unterstützt Epoll, Kqueue und Solaris' Event Ports.
82 root 1.1
83     Einige Backends sind sehr begrenzt (Kqueue z.B. ist auf fast allen System
84 root 1.9 kaputt und supported bestenfalls Sockets) aber in andere Backends
85 root 1.1 integrierbar, so kann man z.B. ein Kqueue-Backend (supported nur Sockets
86 root 1.2 zuverlässig auf FreeBSD) in ein "herkömmliches" Poll-basiertes Backend
87 root 1.1 integrieren.
88    
89 root 1.3 =item Watcher-Typen
90 root 1.1
91 root 1.2 Neben den üblichen I/O Watchern und Timern (derer es zwei grundsätzlich
92 root 1.1 verschiedene Typen in EV gibt), bietet EV noch speziellere
93 root 1.2 Watchertypen für POSIX-Signale, Prozess-Watcher, Idle-Watcher (für
94 root 1.1 "Hintergrundprozesse"), Prepare/Check-Watcher, mit denen man EV-fremde
95     Event-Modelle oder -Benutzer integrieren kann und Stat-Watcher, mit denen
96 root 1.2 man Dateisystemobjekte auf Veränderungen überwachen kann. Ganz spezielle
97 root 1.1 Watcher, um C<fork()> zu erkennen oder andere Backends zu integrieren gibt
98 root 1.2 es natürlich auch.
99 root 1.1
100 root 1.3 =item Kompatibilität
101    
102     EV wird von AnyEvent voll unterstützt, so daß Module oder Programme, die
103     AnyEvent benutzen, ohne Quellcodeänderungen sofort mit EV benutzt werden
104     können.
105    
106     =item C-Schnittstelle
107 root 1.1
108     Das EV-Modul exportiert die komplette Libev-API auch auf XS-Ebene, was
109     so nur noch Event bietet (bei anderen Modulen muss man auf positive
110     Eigenschaften von Shared-Libraries vertrauen).
111    
112     =back
113    
114    
115     =head1 Warum?
116    
117     EV ist, wie die zugrunde liegende Libev, sehr jung (Ende 2007 erschien
118     die erste Version), und die Entstehung war mehr Zufall als Absicht: Seit
119 root 1.2 ca. 1998 benutze ich regelmäßig und viel das Event-Modul, welches
120     problemlos als das ausgereifteste der verfügbaren Event-Module gelten
121 root 1.1 durfte.
122    
123 root 1.2 Im Laufe der Jahre stieß ich auf eine Menge kleinerer Probleme mit anderen
124 root 1.1 Event-Modellen (siehe weiter oben), doch die Anstrengung, eine eigene
125     Bibliothek zu schreiben, wollte ich nicht aufbringen.
126    
127 root 1.2 Speicherverbrauch war eigentlich nie ein Problem, die Beschränkung auf
128 root 1.1 C<select> und C<poll> schon eher, aber man hat ja schnelle Rechner die
129     das kompensieren (und wenn man nicht drauf achtet, was die Rechenzeit
130 root 1.2 verbraucht, stört es ja sowieso nie).
131 root 1.1
132 root 1.2 An die echten Fehler in z.B. Event gewöhnt man sich mit der Zeit, bzw.
133 root 1.1 findet mehr oder weniger akzeptable Umleitungen um das Problem, oder
134 root 1.2 vermeidet den Einsatz in solchen Fällen ganz.
135 root 1.1
136     Eines Tages kam jedoch die Notwendigkeit, wirklich viele Filehandles
137 root 1.2 effizient zu verwalten, und da Libevent sowas wie der Standard für
138     Performance zu sein schien und es dafür keine Perl-Schnittstelle gab
139     (das ist falsch, es gab eine, nämlich C<Event::Lib>, aber ich habe sie
140 root 1.1 trotz suchens auf CPAN nicht wahrgenommen), fing' ich an, eine eigene
141     Schnittstelle zu Libevent zu schreiben.
142    
143 root 1.2 Wenig erfreut war ich, als ich herausfand, daß Libevent die gleichen
144 root 1.1 Probleme wie Tk hat (nicht mehrere Watcher auf einem Filehandle) und auch
145 root 1.2 nicht wenige Schwächen in der API. Das Erlebnis war derart frustrierend,
146 root 1.9 daß ich mich entschieden habe, endgültig 'mein eigenes Ding' zu machen. Wie
147 root 1.1 erwartet, war es mehr Arbeit, als ich eigentlich investieren wollte,
148 root 1.2 aber nach einigen Monaten hatte ich etwas gebrauchsfähiges, daß sogar
149     bei Benchmarks gegenüber dem "Standard" (nämlich Libevent) hervorragend
150 root 1.1 abschneidet.
151    
152     Da die meisten meiner Module AnyEvent benutzen, und die API von EV (im
153 root 1.2 Geiste...) der von Event ähnelt, war die Umstellung aller meiner wichtigen
154 root 1.1 Projekte (gvpe, rxvt-unicode, Deliantra, mein Webserver sowie mehrere
155 root 1.2 kommerzielle Anwendungen) kein Problem, was natürlich ein sehr guter Test
156     für das Modul war (und ist).
157 root 1.1
158     EV ist somit das Ergebnis von knapp 10 Jahren Erfahrung mit
159 root 1.2 anderen Event-Modellen, deren Stärken und Schwächen und deren
160 root 1.1 Perl-Schnittstelle: alle mir bekannten Probleme wurden adresssiert.
161    
162    
163     =head1 Wie?
164    
165 root 1.3 Nach so viel Blabla wird's Zeit für Code-Beispiele.
166 root 1.1
167     Einen langweiligen Timer realisiert man so.
168    
169     use EV;
170    
171     my $timer = EV::timer 1, 2, sub {
172 root 1.3 warn "zeitstempel: " . EV::now;
173 root 1.1 warn "man rief' mich auf nach 1s dann alle 2s. yeah.";
174     };
175    
176     EV::loop;
177    
178     Das gibt nach einer Sekunde ein warn, und danach alle zwei Sekunden, bis
179     in alle Ewigkeit/Reset/SIGINT etc.
180    
181 root 1.2 EV::loop kehrt automatisch zurück, wenn es keine aktiven Watcher mehr gibt
182 root 1.1 (das nennt man "Deadlock"):
183    
184     my $delay = EV::timer 1, 0, sub {
185     warn "nur einmal nach 1s werde ich aufgerufen.\n";
186     };
187    
188     EV::loop;
189    
190 root 1.2 Das läuft nur für eine Sekunde. Wichtig ist, daß man das Watcher-Objekt,
191 root 1.1 das der Konstruktor liefert, auch aufbewahrt, denn wenn man es vergisst,
192     wird der Watcher automatisch deaktiviert. Hier kehrt C<EV::loop> sofort
193 root 1.2 zurück, wenn keine sonstigen Watcher aktiv sind, denn der Timer wird
194     erzeugt, gestartet und sofort wieder gelöscht:
195 root 1.1
196     EV::timer 10, 10, sub { };
197     EV::loop;
198    
199     I/O-Watcher gehen genauso einfach. Das folgende Beispiel "loop"ed so
200     lange, bis man auf STDIN eine Zeile die mit C<q> beginnt, eingibt (z.b.
201     "quit"):
202    
203     my $stdin_watcher = EV::io *STDIN, EV::READ, sub {
204     my $line = <STDIN>;
205    
206 root 1.2 # $_[0] enthält das watcher-objekt
207 root 1.1 $_[0]->stop if $line =~ /^q/;
208     };
209    
210     EV::loop;
211    
212 root 1.3 Alternativ kann man den Watcher auch "einfach" C<undef>'en (die
213     Sichtbarkeit von my-Variablen in Perl macht das ein bißchen eklig):
214 root 1.1
215     my $stdin_watcher;
216     $stdin_watcher = EV::io *STDIN, EV::READ, sub {
217     my $line = <STDIN>;
218    
219     undef $stdin_watcher if $line =~ /^q/;
220     };
221    
222     EV::loop;
223    
224 root 1.2 =head2 Spezialitäten
225 root 1.1
226 root 1.3 Nach dem Standardkram, hier ein paar Spezialitäten, die so wahrscheinlich
227     nur mit EV gehen.
228    
229     =over 4
230    
231     =item Ein Watcher, der jeden Tag um Mitternacht lokaler Zeit seinen
232     Callback aufruft (genauer: zur nächsten Mitternacht nach 23:59:59 des
233     aktuellen Tages. Für Details muß ich auf die Manpage verweisen):
234    
235     use EV;
236     use Time::Local;
237    
238     my $geisterstunde = EV::periodic 0, 0, sub {
239     my ($w, $now) = @_;
240    
241     # berechne den nächsten Zeitpunkt des "Feuerns":
242     my ($y, $m, $d) = (localtime $now)[5, 4, 3];
243     1 + timelocal 59, 59, 23, $d, $m, $y
244     }, sub {
245     warn "buh!";
246     };
247    
248     Der erste Callback berechnet auf Zuruf von EV die nächste Mitternacht.
249     Sollte sich die Systemzeit verändern (z.B. ein paar Jahre zurückfallen),
250     ruft EV den Callback automatisch erneut auf.
251    
252     =item Überwache F</var/log/messages> auf Veränderungen (die Größe
253 root 1.7 sollte sich dabei verändern: Wenn auch mtime-Änderungen überwacht werden solle, wird es
254     etwas komplexer, wie in der Manpage beschrieben):
255 root 1.3
256     my $logwatcher = EV::stat "/var/log/messages", 10, sub {
257     warn "/var/log/messages size is now ", ($_[0]->attr)[7];
258     };
259    
260     =item Überwachung einer Perl-Variable auf Veränderung zwischen zwei
261     Iterationen der EV-Ereignis-Schleife:
262    
263     my $var;
264    
265     my $oldval = $var;
266     my $checkvar = EV::prepare sub {
267     if ($oldval ne $var) {
268     warn "variable has changed from $oldval to $var\n";
269     $oldval = $var;
270     }
271     };
272    
273 root 1.13 Ein C<prepare>-Watcher wird ausgeführt bevor EV nach neuen Ereignissen
274     Ausschau hält, während ein C<check>-Watcher direkt danach ausgeführt
275     wird. Auf diese Weise kann man EV-fremde Ereignisse in EV integrieren,
276     z.B. kann man in einem C<prepare>-Watcher neue Watcher erzeugen für z.B.
277     die Sockets von C<Net::SNMP> während man in einem C<check>-Watcher dann
278     auf entsprechende Ereignisse reagieren kann.
279    
280 root 1.3 =item Einbetten von Kqueue in ein anderes Backend (z.B. für FreeBSD, Mac
281     OS X), damit man wenigstens Sockets effizient benutzen kann:
282    
283     my $socket_loop;
284    
285     # Erzeuge eine Kqueue-loop WENN Kqueue unterstützt wird UND NICHT
286     # schon für die Standard-Schleife verwendet wird:
287     if (
288     (EV::backend & (EV::BACKEND_POLL | EV::BACKEND_SELECT))
289     && (EV::supported_backends & EV::embeddable_backends & EV::BACKEND_KQUEUE)
290     ) {
291     $socket_loop = new EV::Loop EV::BACKEND_KQUEUE | EV::FLAG_NOENV;
292     }
293    
294     # Ansonsten benutze die Standard-Schleife:
295     $socket_loop ||= EV::default_loop;
296    
297     # Erzeuge einen Socket-Watcher:
298     my $watcher = $socket->io ($socket_fh, EV::READ, sub { ... });
299    
300     Statt die globalen Konstruktoren in EV zu verwenden kann man sie auch
301     über Methodenaufrufe eines EV::Loop-Objektes erreichen.
302    
303     =item Benutzung von EV von XS aus.
304    
305     Im Makefile.PL:
306    
307     use EV::MakeMaker;
308    
309     WriteMakefile (EV::MakeMaker::ev_args (
310     ... normale MakeMaker-Argumente
311     ));
312    
313     Im .XS-File:
314    
315     #include "EVAPI.h"
316    
317     static ev_timer mytimer;
318    
319     static void
320 root 1.8 mycb (EV_P_ ev_timer *w, int revents)
321 root 1.3 {
322     // zuerst nach 1s, dann alle 2s
323     }
324    
325     ...
326    
327     BOOT:
328     I_EV_API ("<modulname>");
329     ev_timer_init (&mytimer, mycb, 1., 2.);
330     ev_timer_start (EV_DEFAULT, &mywatcher);
331    
332     =back
333    
334 root 1.1
335     =head1 Und wie noch?
336    
337 root 1.3 Auf CPAN gibt es einige Module, die sich direkt oder indirekt mit EV beschäftigen.
338    
339     =head2 Module, die direkt mit EV in Bezug stehen
340    
341     =over 4
342    
343     =item EV::ADNS
344    
345     Eine Schnittstelle zu libadns, einer asynchronen DNS-Resolver-Bibliothek,
346     die sich in EV integriert. Ein gutes Beispiel, wie man eine "EV-fremde"
347     C-Bibliothek in libev/EV integriert (auf XS-Ebene).
348    
349     =item Net::SNMP::EV
350    
351     Ein Hack, der die Non-Blocking-Aufrufe des Net::SNMP-Moduls in EV
352     integriert: Net::SNMP unterstützt parallel Anfragen, benutzt aber sein
353     eigenes, internes, Event-Modell. Dieses Modul bildet es auf EV ab.
354    
355     Einfaches Laden genügt und schon benutzt Net::SNMP für I/O und Timer das
356     EV-Modul.
357    
358     Das Modul ist ein gutes Beispiel dafür, wie man "EV-fremde" Perl-Module
359     in EV integrieren kann (auf Perl-Ebene).
360    
361     =item Glib::EV
362    
363     Dieses Modul ersetzt das "backend" (normalerweise poll oder select) von
364     Glib (bzw. libglib) durch EV. Dies ist üblicherweise (z.B. wenn man
365     epoll verwendet) etwas langsamer als Glib selbst, wenn man jedoch wenige
366     Glib-Watcher (z.B. nur die von Gtk+) und viele (also mehr als 1-2 :)
367     EV-Watcher verwendet, ergibt dies einen Nettogewinn, vor allem, weil Glib
368 root 1.9 die ineffizienteste Implementation eines Event-Modells ist, die ich je
369     gesehen habe.
370 root 1.3
371     Laden des Moduls genügt, man muss jedoch die Hauptschleife von Glib
372     oder Gtk+ benutzen, C<EV::loop> hilft nicht viel, da Glib die Kontrolle
373     behalten muss.
374    
375     Arbeitet ähnlich wie EV::ADNS, ist aber komplexer.
376    
377     =item EV::Glib
378    
379     Mit diesem Modul kann man EV-Watcher in bestehenden Glib-Programmen
380     benutzen.
381    
382     Fast identisch mit Glib::EV, jedoch wird hier der "MainContext" von Glib
383     in EV integriert, d.h. die Watcher von Glib werden bei Iterationen von EV
384     mitgeprüft. Dies ist genauso ineffizient wie C<Glib::EV>, es amortisiert
385     sich aber sobald man einige EV-Watcher benutzt.
386    
387     Laden des Moduls genügt, man muss jedoch die Hauptschleife von EV
388     aufrufen, was dazu führt, daß sowohl die EV-eigenen als auch die
389     Glib-eigenen Watcher betreut/abgefragt werden.
390    
391     Mit diesem Modul kann man Glib (doer Gtk) in einem EV-Programm benutzen.
392    
393 root 1.4 =item POE::Loop::EV
394    
395     Offenbar ein Backend zu EV von POE. Hab's nicht ausprobiert, die Kerle
396     sollten aber AnyEvent benutzen, damit kriegen sie automatisch EV und alles
397     andere was AnyEvent unterstützt.
398    
399 root 1.3 =back
400    
401     =head2 Module, die EV benutzen können
402    
403     =over 4
404    
405     =item AnyEvent
406    
407     AnyEvent unterstützt C<EV> (und C<Coro::EV>) explizit, d.h. bestehende
408     Anwender von AnyEvent kommen sofort in den Genuß von EV.
409    
410     AnyEvent + EV ist sogar schneller als die meisten (bzw. alle von mir
411     getesteten) Event-Module, und das, obwohl AnyEvent vergleichsweise viel
412     Aufwand leisten muss.
413    
414     =item Coro, Coro::EV
415    
416     Die Filehandle- und Timer-Abstraktionen von C<Coro> (C<Coro::Handle>,
417     C<Coro::Socket>, C<Coro::Timer>) unterstützen EV direkt (über
418     C<Coro::EV>). EV ist das effizienteste direkt unterstützte Event-Modul in
419 root 1.11 C<Coro>.
420 root 1.4
421     C<Coro::EV> hat neben der Unterstützung von C<Coro::Handle> noch
422     Hilfsfunktionen, um einmalige Verzögerungen u.ä. in Coroutinen zu
423     benutzen.
424 root 1.3
425 root 1.4 Sollte C<EV::ADNS> installiert sein, so wird es von C<Coro::Util> (und
426     damit auch C<Coro::Socket>) für DNS-Anfragen benutzt, statt einen
427     separaten Prozess zu forken (was sehr langsam sein kann).
428    
429     =item IO::AIO / Coro::AIO
430    
431     Haben direkt nichts mit EV zu tun (außer, daß sie mit EV gut
432     funktionieren), aber für jedes ereignisgesteuerte Programm ein Muss, da
433 root 1.9 man damit ereignisgesteuert (und asynchron) auf das Dateisystem zugreifen
434 root 1.4 kann, mit Coro::AIO sogar ähnlich einfach wie mit den eingebauten
435     Perl-Funktionen.
436    
437     =item BDB / Coro::BDB
438 root 1.3
439 root 1.4 Was IO::AIO für's Dateisystem ist, ist BDB für die Berkeley DB, nämlich
440 root 1.9 ein Modul, mit dem man ereignisgesteuert die Berkeley DB benutzen kann.
441 root 1.3
442     =back
443    
444     =head2 Werbung
445    
446     Ok, pure Werbung, aber es gibt noch andere Programme, die Libev benutzen.
447    
448     =over 4
449    
450     =item GVPE, das GNU Virtual Private Ethernet
451    
452 root 1.10 In der nächsten (2.2) Release wird es Libev benutzen. Bringt total viel :->
453 root 1.3
454     http://savannah.gnu.org/projects/gvpe
455    
456     =item Rxvt-Unicode
457    
458     Das allerbeste Terminal überhaupt, vor allem, weil es einen
459 root 1.9 Perl-Interpreter embeddet. Und dazu benutzt es (ab Version 8.4 oder so)
460 root 1.3 auch Libev. Leider ohne EV, sondern mit eigener Perl-Schnittstelle, aber
461     na gut, man kann nicht alles haben.
462    
463     http://software.schmorp.de/pkg/rxvt-unicode.html
464    
465     =item Deliantra
466    
467     Das allergeilste Online-RPG wo gibt, vor allem, weil es Perl embeddet,
468     einen ganzen vollen Interpreter. Nicht nur, es benutzt auch Coro, IO::AIO,
469     BDB uvm., und der OpenGL-supergeile-Grafik-mach-Client ist ebenfalls
470     in Perl geschrieben und benutzt EV, BDB... den Rest kann man sich
471     vorstellen. Ein Must-See-Must-Have, vor allem wegen des super Retro-Stils!
472    
473 root 1.5 http://www.deliantra.net/
474    
475 root 1.3 =item OpenMPI
476    
477     Wird, nach eigener Aussage, in der nächsten Release ebenfalls Libev
478     benutzen. Kein embeddetes Perl in Sicht.
479    
480 root 1.5 http://www.openmpi.org/
481    
482 root 1.3 =back
483    
484    
485 root 1.2 =head1 Hä?
486 root 1.1
487 root 1.3 Ich kann (bzw. wollte) hier nur eine kurze Übersicht geben bzw. einen
488     Geschmack vermitteln und eventuell neugierig machen.
489    
490     Mehr Informationen gibt es auf der libev-Manpage:
491    
492     http://libev.schmorp.de/
493    
494     Von dort gibt es auch einen Link zu EV (der Perl-Schnittstelle), dessen
495     Doku, und einem Benchmark mit Libevent:
496    
497     http://pod.tst.eu/http://cvs.schmorp.de/EV/EV.pm
498     http://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod
499     http://libev.schmorp.de/bench.html
500    
501     =head1 Autor
502    
503     Marc Lehmann <schmorp@schmorp.de>.