Jump to content

Recommended Posts

Geschrieben

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.

 

Geschrieben

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.

Geschrieben

Mh, gucke ich mir an. Wäre zumindest eine mögliche Erklärung. Interessant finde ich gerade auch das sowohl hier als auch im IO16 Thread C# verwendet wird, vielleicht ist es etwas C# spezifisches?

Geschrieben

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.

Geschrieben

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).

Geschrieben

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.

Geschrieben

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.

Geschrieben

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!

Join the conversation

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

Gast
Reply to this topic...

×   Du hast formatierten Text eingefügt.   Formatierung jetzt entfernen

  Only 75 emoji are allowed.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Clear editor

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.

×
×
  • Neu erstellen...