Jump to content

WLAN delay, Socket flush() notwendig?


Recommended Posts

Hallo zusammen,

 

ich habe ein Testprogramm, welches über einen Switch des Quad-Relay eine Leuchtdiode so lange einschaltet, wie ein Button in einer GUI gedrückt gehalten wird. Ist das Relais über einen Master per USB verbunden kann ich quasi "morsen": die Diode reagiert ohne merkliche Verzögerung. 3-4 Ein- / Ausschaltvorgänge pro Sekunde sind problemlos möglich, so schnell wie ich eben clicken kann.

 

Per WLAN-Extension angesprochen reagiert das Relais träge: nur noch 1-2 Ein- / Ausschaltvorgänge pro Sekunde sind möglich. Man merkt eine erhebliche Verzögerung.

 

Zum Schalten brauche ich einen "getValue()" und einen "setValue()" für das Relais. Der getValue() braucht per USB 1-2ms, per WLAN ca 6-7ms (so meine Messung im Massentest). Aber selbst 7ms würden locker ausreichen, um mehrmals pro Sekunde ohne merkliche Verzögerung zu schalten. Ein Trace gibt aus, dass jeder 2. oder 3. Schaltvorgang 180ms benötigt, die übrigen 6-8ms (wie erwartet).

 

Kann man diese Verzögerung noch irgendwie erklären?

 

Mir ist aufgefallen, dass die Methode IPConnection.write() keinen out.flush() beinhaltet (Java API). Ein out.flush() wird nur im Konstruktor der IPConnection aufgerufen, hier halte ich ihn nicht für notwendig.

 

Theoretisch kann das dazu führen, dass Verzögerungen auftreten, gerade wenn wenig Datenpakete übertragen werden. Genauso "riskant" wäre es, wenn der Brick die Daten zurück sendet, ohne den Stream zu flushen. Dann kann die Response merklich langsamer werden.

 

Anders kann ich mir nicht erklären, dass einzelne Pakete teilweise extrem langsam sind. Im Massentest fällt sowas nicht so auf, weil immer genügend Daten im Stream stehen, damit der dann gesendet wird.

 

Link to comment
Share on other sites

Ja, der Effekt passt zum genannten Thread oder ist gar der Gleiche. Interessant ist für mich, dass nicht jedes Paket langsam ist, sondern nur jedes 2./3. Und im Massentest (wenn viele Pakete über die Leitung gehen) ist es nicht nachvollziehbar: der Durchschnitt ist im erwarteten Bereich (6-7ms) und somit OK. Das sieht für mich nach einem fehlenden "flush()" (oder Ähnliches) auf Brick-Seite aus.

 

Ich habe den "flush()" mal in die IPConnection auf Anwendungsseite eingebaut. Das hat den Effekt nicht behoben.

Link to comment
Share on other sites

Oh, ich dachte du nutzt auch C#.

 

Ich hab das mal gerade nachgestellt:

import com.tinkerforge.BrickletIndustrialQuadRelay;
import com.tinkerforge.IPConnection;

public class ExampleSimple {
private static final String host = "192.168.178.108";
private static final int port = 4223;
private static final String UID = "cuw";

public static void main(String args[]) throws Exception {
	IPConnection ipcon = new IPConnection();
	BrickletIndustrialQuadRelay iqr = new BrickletIndustrialQuadRelay(UID, ipcon);
	ipcon.connect(host, port);

	long start;
	long end;
	for(int i = 0; i < 100; i++) {
		Thread.sleep(5000);
		start = System.currentTimeMillis();
		int value = iqr.getValue();
		iqr.setValue(~value);
		end = System.currentTimeMillis();
		System.out.println("time: " + (end - start));
	}
}
}

 

Ergebnis:

olaf@pc:~/build20/java$ java -cp . ExampleSimple

time: 6

time: 6

time: 8

time: 7

time: 7

time: 7

time: 7

time: 8

time: 6

time: 7

time: 7

time: 7

time: 8

time: 8

time: 7

time: 8

time: 7

time: 8

time: 8

time: 7

time: 8

time: 7

time: 7

time: 7

time: 6

time: 8

time: 7

time: 7

time: 7

time: 7

time: 7

time: 8

time: 6

time: 7

time: 7

time: 8

time: 8

time: 8

time: 8

time: 8

time: 6

time: 7

time: 8

time: 7

time: 9

time: 7

time: 7

time: 8

time: 5

time: 7

time: 7

time: 7

time: 7

time: 7

time: 9

time: 10

time: 6

time: 7

time: 7

time: 7

time: 7

time: 7

time: 7

time: 7

time: 6

time: 8

time: 8

time: 7

time: 8

time: 8

time: 8

time: 8

time: 6

time: 7

time: 9

time: 8

time: 8

time: 7

time: 7

time: 7

time: 6

time: 8

time: 7

time: 7

time: 7

time: 7

time: 7

time: 7

time: 6

time: 8

time: 7

time: 8

time: 8

time: 7

time: 7

time: 8

time: 6

time: 6

time: 7

time: 8

 

Das sieht also alles gut aus. Kannst du das mal bei dir ausführen (UID abändern)? Wenn das Problem damit nicht auftritt, kannst du es so abändern das es auftritt?

 

Eine weitere Idee: Könntest du in der IPConnection.java zum Testen ein "socket.setTcpNoDelay(true);" hinzufügen? Direkt nach dem "socket = new Socket(host, port);" am besten.

Link to comment
Share on other sites

Mit dem Delay 5000 sieht es ähnlich aus, wie bei Dir (6-10ms for get+set).

Sieht die Schleife aber so aus (delay 100ms),

	for(int i = 0; i < 100; i++) {
		Thread.sleep(100);
		start = System.currentTimeMillis();
		int value = iqr.getValue();
		iqr.setValue(~value);
		end = System.currentTimeMillis();
		System.out.println("time: " + (end - start));
	}

 

Dann ändert sich der Output dramatisch:

time: 5

time: 12

time: 100

time: 100

time: 100

time: 100

time: 99

time: 99

time: 100

time: 100

time: 100

time: 99

time: 100

time: 101

time: 103

time: 96

time: 100

time: 99

time: 99

time: 99

time: 100

time: 99

time: 100

time: 100

time: 100

time: 100

time: 99

time: 100

time: 100

time: 100

time: 99

time: 100

time: 101

time: 99

time: 100

time: 103

time: 99

time: 98

time: 103

time: 97

time: 100

time: 101

time: 99

time: 100

time: 100

time: 100

time: 99

time: 100

time: 100

time: 100

time: 100

time: 99

time: 100

time: 101

time: 99

time: 102

time: 100

time: 98

time: 100

time: 100

time: 100

time: 100

time: 100

time: 100

time: 100

time: 100

time: 100

time: 100

time: 100

time: 100

time: 100

time: 101

time: 99

time: 101

time: 98

time: 100

time: 100

time: 100

time: 104

time: 96

time: 102

time: 114

time: 84

time: 99

time: 100

 

Noch etwas gespielt:

5000ms Sleep vor get+set => 5-10ms Response

200ms Sleep vor get+set => 5-10ms Response

150ms Sleep vor get+set => 40-50ms Response (Sleep + Response ~ 200ms)

100ms Sleep vor get+set => 100ms Response (Sleep + Response ~ 200ms)

 

Das scheint immer in Summe auf 200ms rauszulaufen. Alles unter 200ms verzögert sich. geht auch mit Zwischenwerten (130ms Sleep).

Link to comment
Share on other sites

Interessant!

 

Wenn socket.setTcpNoDelay(true) hilft, dann sollte das Problem nicht direkt mit WIFI zusammenhängen, sondern auch über LAN auftreten.

 

Hast du einen 2. Rechner zur Hand an dem du den Stack per USB anschließen und dann noch mal testen kannst?

 

2. Rechner, damit die TCP Kommunikation nicht nur über Localhost geht und das Betriebssystem dann da irgendwas anders macht oder optimiert.

Link to comment
Share on other sites

Ich habe jetzt auch nochmal einen Test von einem 2. Rechner aus gemacht, mit Binding 1.x: Auf dem Zielrechner läuft der Brickd und der Stack ist per USB angeschlossen. 2. Rechner greift über LAN/WLAN auf den Zielrechner auf Port 4223 zu:

 

ist auch verzögert, wenn TCP_NODELAY fehlt; der Effekt liegt also nicht an der WLAN Extension.

Link to comment
Share on other sites

Wow! Das heißt wir hatten diesen "Bug" schon immer in den Bindings. Wer weiß wieviele Leute schon Probleme mit hohen Latenzzeiten hatten, sich aber einfach nicht gemeldet haben :o.

 

Auf jeden Fall vielen Dank für die Hilfe und das Testen!

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...