ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/docs/ev.pod
Revision: 1.10
Committed: Sun Jan 13 03:12:05 2008 UTC (18 years, 8 months ago) by root
Branch: MAIN
Changes since 1.9: +1 -1 lines
Log Message:
*** empty log message ***

File Contents

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