| 1 |
=head1 EV - (noch) ein Event-Modell für Perl |
| 2 |
|
| 3 |
=head1 Was? |
| 4 |
|
| 5 |
EV ist ein Perl-Modul, das Ereignisgesteuertes Programmieren |
| 6 |
unterstützt. Darin unterscheidet es sich erst einmal nicht von anderen |
| 7 |
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 |
=item Korrektheit |
| 17 |
|
| 18 |
Die meisten Ereignis-Bibliotheken funktionieren gut, solange nichts |
| 19 |
unvorhergesehenes passiert. |
| 20 |
|
| 21 |
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 |
sowohl relative Timer ("wecke mich in 10 Minuten auf, egal ob ntpd die |
| 25 |
Uhr ändert oder nicht) als auch absolute Timer ("wecke mich 2008-10-10 |
| 26 |
12:17:23.445 auf, egal wie lange das wirklich dauert" oder gar "wecke |
| 27 |
mich zur nächsten Mitternacht auf"), was kein anderes mir bekanntes |
| 28 |
Event-Modell unterstützt. |
| 29 |
|
| 30 |
Registriert man bei Tk (Event::Lib, ...) zwei Watcher auf denselben |
| 31 |
Filehandle, so kann einer davon verloren gehen (nicht notwendigerweise |
| 32 |
immer der ältere oder neuere). |
| 33 |
|
| 34 |
Stellt man bei Event die "richtigen" Prioritäten ein, kriegt man eine |
| 35 |
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 |
Das alles sind Kleinigkeiten - bis das Programm deshalb mal "hängt", 100% |
| 39 |
Rechenzeit verbraucht oder gar sporadisch versagt. |
| 40 |
|
| 41 |
Außerdem haben viele Event-Modelle (Event, Glib, Tk...) ein von Perl |
| 42 |
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 |
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 |
wiederherstellt, sofern es benutzt wird. |
| 52 |
|
| 53 |
=item Geschwindigkeit |
| 54 |
|
| 55 |
EV benutzt "die richtigen" Algorithmen zur Verwaltung: Heaps für die |
| 56 |
Verwaltung der Timer (keine lineare Liste oder ähnliches wie alle |
| 57 |
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 |
Auch die Perl-Schnittstelle selbst wurde geschrieben, um unnötige |
| 68 |
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 |
=item Skalierbarkeit |
| 77 |
|
| 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 |
Backend: Libev unterstützt Epoll, Kqueue und Solaris' Event Ports. |
| 82 |
|
| 83 |
Einige Backends sind sehr begrenzt (Kqueue z.B. ist auf fast allen System |
| 84 |
kaputt und supported bestenfalls Sockets) aber in andere Backends |
| 85 |
integrierbar, so kann man z.B. ein Kqueue-Backend (supported nur Sockets |
| 86 |
zuverlässig auf FreeBSD) in ein "herkömmliches" Poll-basiertes Backend |
| 87 |
integrieren. |
| 88 |
|
| 89 |
=item Watcher-Typen |
| 90 |
|
| 91 |
Neben den üblichen I/O Watchern und Timern (derer es zwei grundsätzlich |
| 92 |
verschiedene Typen in EV gibt), bietet EV noch speziellere |
| 93 |
Watchertypen für POSIX-Signale, Prozess-Watcher, Idle-Watcher (für |
| 94 |
"Hintergrundprozesse"), Prepare/Check-Watcher, mit denen man EV-fremde |
| 95 |
Event-Modelle oder -Benutzer integrieren kann und Stat-Watcher, mit denen |
| 96 |
man Dateisystemobjekte auf Veränderungen überwachen kann. Ganz spezielle |
| 97 |
Watcher, um C<fork()> zu erkennen oder andere Backends zu integrieren gibt |
| 98 |
es natürlich auch. |
| 99 |
|
| 100 |
=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 |
|
| 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 |
ca. 1998 benutze ich regelmäßig und viel das Event-Modul, welches |
| 120 |
problemlos als das ausgereifteste der verfügbaren Event-Module gelten |
| 121 |
durfte. |
| 122 |
|
| 123 |
Im Laufe der Jahre stieß ich auf eine Menge kleinerer Probleme mit anderen |
| 124 |
Event-Modellen (siehe weiter oben), doch die Anstrengung, eine eigene |
| 125 |
Bibliothek zu schreiben, wollte ich nicht aufbringen. |
| 126 |
|
| 127 |
Speicherverbrauch war eigentlich nie ein Problem, die Beschränkung auf |
| 128 |
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 |
verbraucht, stört es ja sowieso nie). |
| 131 |
|
| 132 |
An die echten Fehler in z.B. Event gewöhnt man sich mit der Zeit, bzw. |
| 133 |
findet mehr oder weniger akzeptable Umleitungen um das Problem, oder |
| 134 |
vermeidet den Einsatz in solchen Fällen ganz. |
| 135 |
|
| 136 |
Eines Tages kam jedoch die Notwendigkeit, wirklich viele Filehandles |
| 137 |
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 |
trotz suchens auf CPAN nicht wahrgenommen), fing' ich an, eine eigene |
| 141 |
Schnittstelle zu Libevent zu schreiben. |
| 142 |
|
| 143 |
Wenig erfreut war ich, als ich herausfand, daß Libevent die gleichen |
| 144 |
Probleme wie Tk hat (nicht mehrere Watcher auf einem Filehandle) und auch |
| 145 |
nicht wenige Schwächen in der API. Das Erlebnis war derart frustrierend, |
| 146 |
daß ich mich entschieden habe, endgültig 'mein eigenes Ding' zu machen. Wie |
| 147 |
erwartet, war es mehr Arbeit, als ich eigentlich investieren wollte, |
| 148 |
aber nach einigen Monaten hatte ich etwas gebrauchsfähiges, daß sogar |
| 149 |
bei Benchmarks gegenüber dem "Standard" (nämlich Libevent) hervorragend |
| 150 |
abschneidet. |
| 151 |
|
| 152 |
Da die meisten meiner Module AnyEvent benutzen, und die API von EV (im |
| 153 |
Geiste...) der von Event ähnelt, war die Umstellung aller meiner wichtigen |
| 154 |
Projekte (gvpe, rxvt-unicode, Deliantra, mein Webserver sowie mehrere |
| 155 |
kommerzielle Anwendungen) kein Problem, was natürlich ein sehr guter Test |
| 156 |
für das Modul war (und ist). |
| 157 |
|
| 158 |
EV ist somit das Ergebnis von knapp 10 Jahren Erfahrung mit |
| 159 |
anderen Event-Modellen, deren Stärken und Schwächen und deren |
| 160 |
Perl-Schnittstelle: alle mir bekannten Probleme wurden adresssiert. |
| 161 |
|
| 162 |
|
| 163 |
=head1 Wie? |
| 164 |
|
| 165 |
Nach so viel Blabla wird's Zeit für Code-Beispiele. |
| 166 |
|
| 167 |
Einen langweiligen Timer realisiert man so. |
| 168 |
|
| 169 |
use EV; |
| 170 |
|
| 171 |
my $timer = EV::timer 1, 2, sub { |
| 172 |
warn "zeitstempel: " . EV::now; |
| 173 |
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 |
EV::loop kehrt automatisch zurück, wenn es keine aktiven Watcher mehr gibt |
| 182 |
(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 |
Das läuft nur für eine Sekunde. Wichtig ist, daß man das Watcher-Objekt, |
| 191 |
das der Konstruktor liefert, auch aufbewahrt, denn wenn man es vergisst, |
| 192 |
wird der Watcher automatisch deaktiviert. Hier kehrt C<EV::loop> sofort |
| 193 |
zurück, wenn keine sonstigen Watcher aktiv sind, denn der Timer wird |
| 194 |
erzeugt, gestartet und sofort wieder gelöscht: |
| 195 |
|
| 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 |
# $_[0] enthält das watcher-objekt |
| 207 |
$_[0]->stop if $line =~ /^q/; |
| 208 |
}; |
| 209 |
|
| 210 |
EV::loop; |
| 211 |
|
| 212 |
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 |
|
| 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 |
=head2 Spezialitäten |
| 225 |
|
| 226 |
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 |
sollte sich dabei verändern: Wenn auch mtime-Änderungen überwacht werden solle, wird es |
| 254 |
etwas komplexer, wie in der Manpage beschrieben): |
| 255 |
|
| 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 |
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 |
=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 |
mycb (EV_P_ ev_timer *w, int revents) |
| 321 |
{ |
| 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 |
|
| 335 |
=head1 Und wie noch? |
| 336 |
|
| 337 |
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 |
die ineffizienteste Implementation eines Event-Modells ist, die ich je |
| 369 |
gesehen habe. |
| 370 |
|
| 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 |
=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 |
=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 |
C<Coro>. |
| 420 |
|
| 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 |
|
| 425 |
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 |
man damit ereignisgesteuert (und asynchron) auf das Dateisystem zugreifen |
| 434 |
kann, mit Coro::AIO sogar ähnlich einfach wie mit den eingebauten |
| 435 |
Perl-Funktionen. |
| 436 |
|
| 437 |
=item BDB / Coro::BDB |
| 438 |
|
| 439 |
Was IO::AIO für's Dateisystem ist, ist BDB für die Berkeley DB, nämlich |
| 440 |
ein Modul, mit dem man ereignisgesteuert die Berkeley DB benutzen kann. |
| 441 |
|
| 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 |
In der nächsten (2.2) Release wird es Libev benutzen. Bringt total viel :-> |
| 453 |
|
| 454 |
http://savannah.gnu.org/projects/gvpe |
| 455 |
|
| 456 |
=item Rxvt-Unicode |
| 457 |
|
| 458 |
Das allerbeste Terminal überhaupt, vor allem, weil es einen |
| 459 |
Perl-Interpreter embeddet. Und dazu benutzt es (ab Version 8.4 oder so) |
| 460 |
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 |
http://www.deliantra.net/ |
| 474 |
|
| 475 |
=item OpenMPI |
| 476 |
|
| 477 |
Wird, nach eigener Aussage, in der nächsten Release ebenfalls Libev |
| 478 |
benutzen. Kein embeddetes Perl in Sicht. |
| 479 |
|
| 480 |
http://www.openmpi.org/ |
| 481 |
|
| 482 |
=back |
| 483 |
|
| 484 |
|
| 485 |
=head1 Hä? |
| 486 |
|
| 487 |
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>. |