2013-02-21 8 views
21

L'invio di lotti di piccoli pacchetti da parte di UDP richiede più risorse (cpu, compressione da zlib, ecc ...). Ho letto here che l'invio di un grosso pacchetto di ~ 65kBYTEs da parte di UDP probabilmente fallirebbe, quindi penso che l'invio di un sacco di pacchetti più piccoli avrebbe avuto successo più spesso, ma poi il sovraccarico computazionale di usare più potenza di elaborazione (o almeno quello che ho sto assumendo). La domanda è fondamentalmente questa; Qual è lo scenario migliore per inviare i pacchetti di massimo successo e ridurre al minimo il calcolo? Esiste una dimensione specifica che funziona la maggior parte del tempo? Sto usando Erlang per un server ed Enet per il client (scritto in C++). Usando anche la compressione Zlib e invio gli stessi pacchetti a tutti i client (la trasmissione è il termine che indovino).La dimensione del pacchetto udp più affidabile ed efficiente?

risposta

22

La dimensione massima di UDP payload che, il più delle volte, non causerà la frammentazione IP è

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 parlato di 534 byte ma vorrei fissarlo al 508. Questo è il numero di byte che DI SICURO non causano la frammentazione, perché la dimensione minima MTU che un host può impostare è e IP header max size può essere 60 bytes(508 = 576 MTU - 60 IP - 8 UDP)

Dal modo in cui proverei ad andare con 1472 byte perché 1500 è un valore abbastanza standard.

Utilizzare 1492 anziché 1500 per il calcolo se si sta attraversando una connessione PPPoE.

+0

Il numero minimo * IP * MTU è 576. Non include le intestazioni Ethernet, quindi fornirebbe 548 effettivamente. – EJP

+0

Hai ragione ... ho corretto il calcolo considerando anche che la dimensione massima dell'header IP può raggiungere i 60 byte –

+0

508 è fantastico! –

4

534 byte. Ciò è richiesto per essere trasmesso senza frammentazione. Può ancora essere perso, naturalmente. Le spese generali dovute alla ritrasmissione dei pacchetti persi e alle stesse spese generali della rete sono di diversi ordini di grandezza più significative di qualsiasi costo della CPU.

+0

Mi chiedo quale sia l'effetto diretto sul pacchetto di frammentazione. Nella mia applicazione, quando vado da 508 a 509, sembra che un '\ 0' sia aggiunto alla fine del 2 ° pacchetto. Mi chiedo se esso dipenda dalla mia particolare implementazione o è un trule? –

+0

@mavErick Il null finale proviene o è erroneamente osservato dal codice. UDP non lo fa. – EJP

-11

Probabilmente stai usando il protocollo sbagliato. UDP è quasi sempre una scelta sbagliata per i dati che ti interessano trasmettere. Si finisce per sovrapporre sequenze, riprovi e logica di integrità in cima, e poi si ha il TCP.

+1

"riprova"? Ma pensavo che fosse il tcp su ... rispedire i pacchetti per portare a termine il lavoro. Lo sto facendo per un gioco online, quindi il Tcp sarà probabilmente troppo lento, o questo è quello che dicono tutti gli altri. – pandoragami

+1

"Tutti" è spesso sbagliato. Se temi che i dati non arrivino, hai bisogno del TCP. –

+0

Ok, allora quale sarebbe la dimensione del pacchetto tcp più efficiente considerando Nagel, ecc. – pandoragami

7

L'invio di lotti di piccoli pacchetti da parte di UDP richiede più risorse?

Sì, lo sarebbe sicuramente! Ho appena fatto un esperimento con un'applicazione di streaming. L'app invia 2000 frame di dati al secondo, con precisione temporale. Il carico utile dati per ogni frame è di 24 byte. Ho usato UDP con sendto() per inviare questi dati a un'app listener su un altro nodo.

Quello che ho trovato è stato interessante. Questo livello di attività ha messo in ginocchio la CPU che inviavo! Sono passato dall'avere circa il 64% del tempo di CPU libero, ad avere circa il 5%! Questo è stato disastroso per la mia applicazione, quindi ho dovuto risolverlo. Ho deciso di sperimentare con le varianti.

In primo luogo, ho semplicemente commentato la chiamata sendto(), per vedere come appariva l'overhead del pacchetto. Circa un colpo dell'1% sul tempo della CPU. Non male. OK ... deve essere la chiamata sendto()!

Quindi, ho eseguito un test rapido per il falso ...Ho chiamato l'API sendto() una sola volta ogni 10 iterazioni, ma ho riempito il record di dati fino a 10 volte la sua lunghezza precedente, per simulare l'effetto dell'assemblaggio di una raccolta di record più piccoli in uno più grande, inviato meno spesso. I risultati sono stati abbastanza soddisfacenti: il 7% di successo della CPU, rispetto al 59% precedente. Sembrerebbe che, almeno sul mio sistema * NIX, l'operazione di invio di un pacchetto sia costosa solo nel sovraccarico di effettuare la chiamata.

Nel caso in cui qualcuno dubiti che il test funzioni correttamente, ho verificato tutti i risultati con l'osservazione di Wireshark delle trasmissioni UDP effettive per confermare che tutto funzionava come dovrebbe.

Conclusione: utilizza MOLTO meno tempo di CPU per inviare pacchetti più grandi meno spesso, quindi la stessa quantità di dati sotto forma di pacchetti più piccoli inviati più frequentemente. Certo, non so cosa succede se UDP inizia a frammentare il tuo datagramma UDP troppo grande ... Voglio dire, non so quanto sovraccarico di CPU questo aggiunge. Cercherò di scoprire (mi piacerebbe conoscere me stesso) e aggiornare questa risposta.