Porównanie wydajności sterowników sieciowych w wersjach w 10 językach programowania

Grupa badaczy z niemieckich uniwersytetów опубликовала Ustalenia eksperyment, podczas którego opracowano 10 wersji standardowego sterownika dla 10-gigabitowych kart sieciowych Intel Ixgbe (X5xx) w różnych językach programowania. Sterownik działa w przestrzeni użytkownika i jest zaimplementowany w językach C, Rust, Go, C#, Java, OCaml, Haskell, Swift, JavaScript i Python. Podczas pisania kodu główny nacisk położono na osiągnięcie jak najlepszej wydajności, biorąc pod uwagę charakterystykę każdego języka. Wszystkie opcje mają identyczną funkcjonalność i składają się z około 1000 linii kodu. Rozwój projektu rozpowszechnianie się na licencji BSD.

Wersja sterownika Rust okazała się bardzo zbliżona wydajnością do sterownika referencyjnego w języku C. Pod obciążeniem przy jednoczesnym wysyłaniu bloków po 32 pakiety sterownik Rust pozostawał nieco w tyle, ale w testach z więcej niż 32 pakietami na blok prędkość praktycznie nie różniła się od sterownika C i wykazała wydajność na poziomie przetwarzania 28 milionów pakietów na sekundę na serwerze z procesorem Xeon E3-1230 v2 3.3 GHz.

Porównanie wydajności sterowników sieciowych w wersjach w 10 językach programowania

Następną niszę pod względem wydajności zajęły sterowniki w językach Go i C#, które pokazały dość zbliżone wyniki (sterownik Go wygrał w testach z blokami do 16 pakietów i zaczął lekko przegrywać w testach z więcej niż 16 pakietami w bloku). Przy 256 pakietach na blok szczytowa wydajność sterownika C# wyniosła około 28 milionów pakietów na sekundę, a sterownika Go około 25 milionów pakietów na sekundę.

Następnie, z dość zbliżonymi wynikami, znalazły się sterowniki
Java, OCaml i Haskell, które już zauważalnie pozostawały w tyle za rozważanymi wcześniej opcjami i nie były w stanie pokonać słupka 12 milionów pakietów na sekundę. Jeszcze większe opóźnienia wykazywały sterowniki Swift i JavaScript, które były w stanie przetwarzać strumienie na poziomie 5 milionów pakietów na sekundę.

Czołówkę rankingu uzupełnił sterownik Pythona, który był w stanie przetworzyć zaledwie 0.14 miliona pakietów na sekundę. Do oceny szybkości interpreterów bez JIT i bez specjalnych optymalizacji wykorzystano implementację Pythona (kod został wykonany przy użyciu CPython 3.7 i nie był kompatybilny z PyPy, ale zauważono, że optymalizacja struktur przechowywania danych mogłaby poprawić wydajność około 10 razy ).

Dodatkowo przeprowadzono testy opóźnień, aby wykazać skuteczność buforowania i wpływ modułu zbierającego elementy bezużyteczne. W ramach testów mierzono opóźnienie po przesłaniu każdego pakietu przez sterownik w porównaniu z dokładnym czasem jego wysłania. Liderami nadal były sterowniki C i Rust, których wyniki były praktycznie nie do odróżnienia dla przepływu 1 miliona pakietów na sekundę (około 20 µs). Dobrze spisał się przetwornik Go, pozostając tylko nieznacznie w tyle za liderami i jednocześnie utrzymując się na poziomie 20 µs. Sterownik C# wykazywał opóźnienia rzędu 50 µs.
Największe opóźnienia wykazywały sterowniki JavaScript i Java (opóźnienia powyżej 300 µs).

Porównanie wydajności sterowników sieciowych w wersjach w 10 językach programowania

Badanie przeprowadzono w celu oceny możliwości opracowania sterowników i komponentów systemu operacyjnego w językach wyższego poziomu niż C. Obecnie 39 z 40 problemów z pamięcią w Linuksie jest związanych ze sterownikami, więc kwestie używania bezpieczniejszego języka i przenoszenia sterowników z jądra do przestrzeni użytkownika pozostają aktualne a producenci już aktywnie eksperymentują w tym kierunku (na przykład Google opracował stos TCP dla systemu operacyjnego). Fuksja w języku Go, firma CloudFlare Utworzony implementacja protokołu QUIC w Rust, Apple przeniósł stos TCP na urządzeniach mobilnych do przestrzeni użytkownika).

W toku prac stwierdzono, że najlepszym kandydatem do rozwoju sterowników jest język Rust. Możliwości Rusta eliminują problemy związane z zarządzaniem pamięcią na niskim poziomie kosztem utraty wydajności w przybliżeniu od 2% do 10% w porównaniu ze sterownikami C. Go i C# są również uważane za odpowiednie do tworzenia komponentów systemu w sytuacjach, w których akceptowalne jest opóźnienie poniżej milisekundy spowodowane przez wyrzucanie elementów bezużytecznych.

Źródło: opennet.ru

Dodaj komentarz