2015-10-29 13 views
9

Stiamo assistendo a un fenomeno bizzarro e inspiegabile con ZeroMQ su Windows 7, l'invio di messaggi su TCP. (O oltre inproc, poiché ZeroMQ utilizza TCP internamente per la segnalazione, su Windows).Perché TCP/IP su Windows7 richiede 500 mandate per il riscaldamento? (w10, w8 dimostrato di non soffrire)

Il fenomeno è che i primi 500 messaggi arrivano più lentamente e più lentamente, con una latenza in costante aumento. Quindi i tempi di latenza e i messaggi arrivano rapidamente, ad eccezione dei picchi causati dalla contesa tra CPU e rete.

Il problema è descritto qui: https://github.com/zeromq/libzmq/issues/1608

E 'sempre 500 messaggi. Se inviamo senza ritardo, i messaggi vengono raggruppati in modo tale che il fenomeno si estenda su diverse migliaia di mandate. Se ritardiamo tra le mandate, vediamo il grafico più chiaramente. Anche il ritardo fino a 50-100 msec tra le mandate non cambia le cose.

Anche la dimensione del messaggio è irrilevante. Ho provato con messaggi a 10 byte e messaggi 10K, con gli stessi risultati.

La latenza massima è sempre 2 msec (2000 usec).

Su scatole Linux non vediamo questo fenomeno.

Quello che vorremmo fare è eliminare questa curva iniziale, in modo che i messaggi vadano su una nuova connessione con la loro normale bassa latenza (circa 20-100 usec).


Aggiornamento: la questione non mostra su Windows 10 né 8. Sembra accadere solo su Windows 7 .

+2

Wild hunch: Mi chiedo se questo potrebbe essere correlato all'autotuning TCP in Win7: http://www.sevenforums.com/network-sharing/74556-enable-disable-tcp-auto-tuning.html – keithmo

+0

Grande intuizione, la stiamo verificando. Risulta che il fenomeno non sembra accadere su Windows 10, né su Windows 8. Quindi potrebbe davvero essere una funzione di autotuning di Windows 7. –

risposta

2

Abbiamo trovato la causa e una soluzione alternativa. Questo è un problema generale con tutte le attività TCP su Windows 7 (almeno) causate dal buffering sul lato ricevente. Puoi trovare alcuni suggerimenti in linea sotto "TCP slow start".

In una nuova connessione, o se il collegamento è inattivo per (Credo) 150 msec o più, il ricevitore buffer i pacchetti in entrata e non fornisce questi per l'applicazione, fino a quando il buffer di ricezione è pieno e/o qualche timeout scade (non è chiaro).

La nostra soluzione alternativa in ZeroMQ, dove stiamo utilizzando i socket TCP per la segnalazione interthread, è quella di inviare una porzione fittizia di dati su nuove coppie di segnali. Ciò obbliga lo stack TCP a funzionare "normalmente" e quindi vediamo latenze consistenti di circa 100-150 usec.

Non sono sicuro se questo è generalmente utile; per la maggior parte delle applicazioni è vantaggioso attendere un po 'in ricezione, quindi lo stack TCP può fornire di più all'applicazione chiamante.

Tuttavia, per le app che inviano molti messaggi di piccole dimensioni, questa soluzione potrebbe essere utile.

Si noti che se la connessione è inattiva, l'avvio lento si ripete, quindi le connessioni dovrebbero battere ogni 100 msec o giù di lì, se questo è fondamentale.

+1

Potresti fornire un link? Il comportamento che descrivi non ha nulla a che fare con TCP slow-start. E ci deve sicuramente essere una soluzione migliore rispetto all'invio di più dati. – EJP

+1

Il problema ZeroMQ è qui: https://github.com/zeromq/libzmq/issues/1608 –

+0

@PieterHintjens Una domanda minore, Pieter, perché il tuo codice di test in github usa una bassa risoluzione s_clock (e lo indica come una ragione per una minore risoluzione temporale dell'esperimento), ** mentre ZeroMQ ha un meraviglioso servizio di utilità Stopwatch.start()/Stopwatch.stop() di 25ns-stepping? "** – user3666197

Problemi correlati