2013-02-21 21 views
21

Wysyłał dużo małych pakietów przez UDP, zabiera więcej zasobów (procesor, kompresja przez zlib, itd.). Przeczytałem here, że wysłanie jednego dużego pakietu ~ 65kBYTE przez UDP prawdopodobnie zakończyłoby się niepowodzeniem, więc myślę, że wysyłanie wielu mniejszych pakietów mogłoby się udać częściej, ale potem pojawia się obciążenie obliczeniowe związane z wykorzystaniem większej mocy obliczeniowej (lub przynajmniej to, co ja zakładam). Pytanie jest w zasadzie to; jaki jest najlepszy scenariusz wysyłania maksymalnych udanych pakietów i utrzymywania obliczeń do minimum? Czy istnieje określony rozmiar, który działa przez większość czasu? Używam Erlanga dla serwera i Enet dla klienta (napisanego w języku C++). Korzystając również z kompresji Zlib i wysyłam te same pakiety do każdego klienta (nadawanie jest terminem, który myślę).Najbardziej niezawodny i efektywny rozmiar pakietu udp?

Odpowiedz

22

Maksymalny rozmiar UDP payload, że przez większość czasu, nie powoduje fragmentacji IP jest

MTU size of the host handling the PDU (most of the case it will be 1500) - 
size of the IP header (20 bytes) - 
size of UDP header (8 bytes) 

1500 MTU - 20 IP hdr - 8 UDP hdr = 1472 bytes 

@EJP mówił o 534 bajtów, ale chciałbym go naprawić do 508. Jest to liczba bajtów na pewno nie powodują rozdrobnienie, ponieważ minimalny rozmiar MTU że gospodarz może ustawić się i IP header max size może 60 bytes(508 = 576 MTU - 60 IP - 8 UDP)

Przy okazji, spróbowałbym użyć 1472 bajtów, ponieważ 1500 jest wartością standardową.

Użyj 1492 zamiast do obliczeń, jeśli przechodzisz przez połączenie PPPoE.

+0

Minimalna wartość MTU * IP * to 576. Nie obejmuje ona nagłówków sieci Ethernet, więc faktycznie dałoby 548. – EJP

+0

Masz rację ... Poprawiłem obliczenia biorąc pod uwagę, że maksymalny rozmiar nagłówka IP może osiągnąć 60 bajtów –

+0

508 jest niesamowity! –

4

534 bajtów. Musi to zostać przekazane bez fragmentacji. Oczywiście nadal można go zgubić. Koszty ogólne wynikające z ponownej transmisji utraconych pakietów i samych kosztów sieci są o kilka rzędów wielkości większe niż jakiekolwiek koszty procesora.

+0

Zastanawiam się, jaki jest bezpośredni wpływ na pakiet fragmentacji. W mojej aplikacji, kiedy przechodzę z 508 na 509, wydaje się, że "\ 0" jest dołączane na końcu drugiego pakietu. Zastanawiam się, czy jest to zależne od mojej konkretnej implementacji czy jest to prawda? –

+0

@mavErick Końcowa wartość null pochodzi z kodu lub jest niepoprawnie przestrzegana przez twój kod. UDP tego nie robi. – EJP

-11

Prawdopodobnie używasz niewłaściwego protokołu. UDP jest prawie zawsze złym wyborem dla danych, których zależy ci na przesyłaniu. Nakładasz na siebie sekwencjonowanie warstw, ponów i logikę integralności, a następnie masz TCP.

+1

"spróbuj ponownie"? Ale myślałem, że to jest właśnie to, o ... ponownym wysyłaniu pakietów, aby wykonać zadanie. Robię to dla gry online, więc tcp najprawdopodobniej będzie zbyt powolne, lub to, co mówią inni. – pandoragami

+1

"Wszyscy" często się mylą. Jeśli obawiasz się, że dane mogą nie dotrzeć, potrzebujesz TCP. –

+0

OK, jaki byłby najskuteczniejszy rozmiar pakietu TCP, biorąc pod uwagę Nagel, itp. – pandoragami

7

Czy wysyłanie partii małych pakietów przez UDP może zająć więcej zasobów?

Tak, zdecydowanie! Właśnie przeprowadziłem eksperyment z aplikacją do przesyłania strumieniowego. Aplikacja przesyła 2000 ramek danych na sekundę, precyzyjnie w czasie. Ładunek danych dla każdej ramki wynosi 24 bajty. Użyłem UDP z sendto(), aby wysłać te dane do aplikacji słuchacza w innym węźle.

To, co znalazłem, było interesujące. Ten poziom aktywności wziął mój procesor wysyłający na kolana! Poszedłem od posiadania około 64% wolnego czasu procesora, do posiadania około 5%! To było katastrofalne dla mojej aplikacji, więc musiałem to naprawić. Postanowiłem eksperymentować z odmianami.

Po pierwsze, po prostu skomentowałem wywołanie sendto(), aby zobaczyć, jak wyglądał narzut zestawu pakietów. Około 1% trafienia czasu procesora. Nie jest zły. OK ... musi być wywołanie sendto()!

Potem zrobiłem szybki test fakeout ...Nazwa API sendto() nazywam tylko raz na 10 iteracji, ale uzupełniłem rekord danych do 10 razy jego poprzedniej długości, aby zasymulować efekt złożenia zbioru mniejszych rekordów w większym, wysyłanym rzadziej. Wyniki były całkiem zadowalające: 7% trafień procesora, w porównaniu z 59% poprzednio. Wydawać by się mogło, że przynajmniej w moim * systemie NIX-podobnym operacja wysyłania pakietu jest kosztowna właśnie w związku z wykonaniem połączenia.

Na wypadek, gdyby ktoś miał wątpliwości, czy test działa poprawnie, zweryfiowałem wszystkie wyniki z obserwacją Wiresharka rzeczywistych transmisji UDP, aby potwierdzić, że wszystko działało tak, jak powinno.

Wniosek: wykorzystuje znacznie mniej czasu procesora do wysyłania większych pakietów rzadziej, potem taką samą ilość danych w postaci mniejszych pakietów wysłanych częściej. Co prawda nie wiem, co się stanie, jeśli UDP zacznie łamać twój nadmiernie duży datagram UDP ... To znaczy, nie wiem, ile to obciążenie procesora dodaje. Postaram się dowiedzieć (sam bym chciał) i zaktualizować tę odpowiedź.

Powiązane problemy