2015-10-29 21 views
9

Wir sehen ein bizarres und unerklärliches Phänomen mit ZeroMQ auf Windows 7, Senden von Nachrichten über TCP. (Oder über inproc, da ZeroMQ TCP intern für Signalisierung unter Windows verwendet).Warum nimmt TCP/IP unter Windows7 500 Sends zum Aufwärmen? (w10, w8 erwies sich nicht zu leiden)

Das Phänomen ist, dass die ersten 500 Nachrichten immer langsamer ankommen und die Latenz stetig steigt. Dann sinkt die Latenz, und Nachrichten kommen konsistent schnell an, mit Ausnahme von Spitzen, die durch CPU-/Netzwerkkonflikte verursacht werden.

Die Frage ist hier beschrieben: https://github.com/zeromq/libzmq/issues/1608

Es konsequent 500 Meldungen ist. Wenn wir ohne Verzögerung senden, werden die Nachrichten in einem Stapel zusammengefasst, so dass wir sehen, dass sich das Phänomen über mehrere tausend Sends erstreckt. Wenn wir zwischen Sends verzögern, sehen wir den Graphen klarer. Selbst Verzögerungen von bis zu 50-100 ms zwischen Sends ändern nichts.

Die Größe der Nachricht ist ebenfalls irrelevant. Ich habe mit 10-Byte-Nachrichten und 10K-Nachrichten mit den gleichen Ergebnissen getestet.

Die maximale Latenz beträgt immer 2 ms (2.000 usec).

Auf Linux-Boxen sehen wir dieses Phänomen nicht.

Wir möchten diese Anfangskurve eliminieren, so dass Nachrichten mit ihrer normalen niedrigen Latenzzeit (etwa 20-100 Usec) eine neue Verbindung eingehen.


Update: das Problem nicht auf Windows nicht zeigen 10 noch 8. Es scheint nur auf Windows passieren.

+2

Wild hunch: Ich frage mich, ob dies mit TCP-Autotuning in Win7 verwandt werden könnte: http://www.sevenforums.com/network-sharing/74556-enable-disable-tcp-auto-tuning.html – keithmo

+0

Großartig Vorsichtige, wir überprüfen es. Stellt sich heraus, das Phänomen scheint nicht auf Windows 10, weder Windows 8 passieren. So könnte es in der Tat eine Windows 7 Autotuning-Funktion sein. –

Antwort

2

Wir haben die Ursache und eine Problemumgehung gefunden. Dies ist ein generelles Problem bei allen TCP-Aktivitäten unter Windows 7 (zumindest), die durch die Pufferung auf der Empfängerseite verursacht werden. Sie können einige Hinweise in der Zeile unter "TCP-langsamer Start" finden.

Auf eine neue Verbindung, oder wenn Verbindung inaktiv ist für (ich glaube) 150 ms oder mehr beträgt, puffert der Empfänger ankommende Pakete und nicht diese für die Anwendung zur Verfügung stellen, bis der Empfangspuffer voll ist und/oder ein Timeout läuft ab (es ist unklar).

Unsere Problemumgehung in ZeroMQ, wo wir TCP-Sockets für Inthread-Signalisierung verwenden, besteht darin, einen Dummy-Datenblock über neue Signalpaare zu senden. Dies zwingt den TCP-Stack dazu, "normal" zu arbeiten, und dann sehen wir konsistente Latenzen von etwa 100-150 usec.

Ich bin mir nicht sicher, ob das allgemein nützlich ist; Für die meisten Anwendungen lohnt es sich, beim Empfang ein wenig zu warten, damit der TCP-Stack mehr an die aufrufende Anwendung liefern kann.

Für Apps, die viele kleine Nachrichten senden, kann diese Problemumgehung hilfreich sein.

Beachten Sie, dass der langsame Start erneut auftritt, wenn die Verbindung im Leerlauf ist. Daher sollten die Verbindungen alle 100 ms einen Heartbeat ausführen, wenn dies kritisch ist.

+1

Können Sie einen Link angeben? Das von Ihnen beschriebene Verhalten hat nichts mit TCP-Slow-Start zu tun. Und es muss sicherlich eine bessere Lösung geben, als mehr Daten zu senden. – EJP

+1

Das ZeroMQ-Problem ist hier: https://github.com/zeromq/libzmq/issues/1608 –

+0

@PieterHintjens Eine kleine Frage, Pieter, warum verwendet Ihr Testcode in GitHub eine niedrige Auflösung s_clock (und geben Sie es als Grund an für eine schlechtere Zeit Auflösung des Experiments, ** während ZeroMQ hat eine wunderbare über 25ns-stepping Stopwatch.start()/Stopwatch.stop() Dienstprogramm Service? "** – user3666197