Jeśli chodzi o filozofię projektowania, libev został stworzony, aby ulepszyć niektóre decyzje architektoniczne w libevent, na przykład globalne użycie zmiennych utrudnia bezpieczne korzystanie z libevent w środowiskach wielowątkowych, struktury obserwatorów są duże, ponieważ łączą we / wy, czas i sygnał w jednym, dodatkowe komponenty, takie jak serwery http i dns, cierpiały z powodu złej jakości implementacji i wynikających z tego problemów z bezpieczeństwem, a liczniki czasu były niedokładne i nie radziły sobie dobrze ze skokami czasu.
Libev próbował ulepszyć każdy z nich, nie używając zmiennych globalnych, ale używając kontekstu pętli dla wszystkich funkcji, używając małych obserwatorów dla każdego typu zdarzenia (obserwator I / O wykorzystuje 56 bajtów na x86_64 w porównaniu do 136 dla libevent), pozwalając na dodatkowe typy zdarzeń, takie jak liczniki czasu oparte na zegarze ściennym w porównaniu z czasem monotonicznym, przerwy między wątkami, przygotowywanie i sprawdzanie obserwatorów w celu osadzenia innych pętli zdarzeń lub osadzenia i tak dalej.
Problem z dodatkowymi komponentami jest „rozwiązany” przez ich całkowity brak, więc libev może być małe i wydajne, ale musisz także szukać gdzie indziej biblioteki http, ponieważ libev po prostu jej nie ma (na przykład istnieje bardzo powiązana biblioteka o nazwie libeio, która obsługuje asynchroniczne operacje we / wy, które mogą być używane niezależnie lub razem z libev, dzięki czemu można je mieszać i dopasowywać).
Krótko mówiąc, libev stara się zrobić tylko jedną rzecz (biblioteka zdarzeń POSIX) i to w możliwie najbardziej efektywny sposób. Libevent stara się dać Ci pełne rozwiązanie (biblioteka zdarzeń, nieblokująca biblioteka I / O, serwer http, klient DNS).
Lub jeszcze krócej, libev stara się podążać za filozofią zestawu narzędzi UNIX, aby robić tylko jedną rzecz, tak dobrze, jak to możliwe.
Zauważ, że jest to filozofia projektowania, którą mogę wyrazić autorytatywnie, ponieważ zaprojektowałem libev. To, czy te cele projektowe zostały faktycznie osiągnięte, czy też filozofia oparta jest na zdrowych zasadach, zależy od Ciebie.
Aktualizacja 2017:
Wiele razy pytano mnie, o jaką niedokładność timera się odnoszę i dlaczego libev nie obsługuje IOCP w systemie Windows.
Jeśli chodzi o timery, libevent planuje timery względem nieznanego czasu bazowego, który jest w przyszłości, bez twojej wiedzy. Libev może z wyprzedzeniem powiedzieć, jakiego czasu bazowego użyje do zaplanowania timerów, co pozwala programom na użycie zarówno podejścia libevent, jak i libev. Ponadto libevent czasami przedwcześnie wygaśnie liczniki czasu, w zależności od zaplecza. Ten pierwszy jest problemem API, drugi można naprawić (i mógł zostać naprawiony od tego czasu - nie sprawdzałem).
Jeśli chodzi o obsługę IOCP - nie sądzę, aby można to zrobić, ponieważ IOCP po prostu nie są wystarczająco potężne. Po pierwsze, potrzebują specjalnego typu gniazda, co jeszcze bardziej ograniczyłoby zestaw uchwytów dozwolonych w oknach (na przykład sopckety używane przez perl są „niewłaściwego” typu dla IOCP). Co więcej, IOCP po prostu w ogóle nie obsługują zdarzeń gotowości we / wy, mogą tylko wykonywać rzeczywiste operacje we / wy. Istnieją obejścia dla niektórych typów uchwytów, takie jak wykonywanie fikcyjnego odczytu 0-bajtowego, ale ponownie ograniczyłoby to typy uchwytów, których można używać w systemie Windows, a ponadto polegałoby na nieudokumentowanym zachowaniu, które prawdopodobnie nie jest wspólne dla wszystkich dostawców gniazd .
O ile mi wiadomo, żadna inna biblioteka zdarzeń również nie obsługuje IOCP w systemie Windows. To, co robi libevent, to oprócz biblioteki zdarzeń, pozwala na kolejkowanie operacji odczytu / zapisu, które następnie można wykonać za pośrednictwem IOCP. Ponieważ libev nie wykonuje operacji we / wy za Ciebie, nie ma możliwości użycia IOCP w samym libev.
Jest to rzeczywiście zgodne z projektem - libev stara się być mały i podobny do POSIX, a okna po prostu nie mają wydajnego sposobu uzyskiwania zdarzeń I / O w stylu POSIX. Jeśli IOCP są ważne, musisz albo sam z nich korzystać, albo rzeczywiście korzystać z wielu innych frameworków, które wykonują za Ciebie I / O i dlatego możesz używać IOCP.