remotecontrol Posted January 20, 2013 at 03:45 PM Share Posted January 20, 2013 at 03:45 PM 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. Quote Link to comment Share on other sites More sharing options...
AuronX Posted January 21, 2013 at 09:24 AM Share Posted January 21, 2013 at 09:24 AM Würde möglicherweise auch hierzu passen: http://www.tinkerunity.org/forum/index.php/topic,1277.0.html Quote Link to comment Share on other sites More sharing options...
remotecontrol Posted January 21, 2013 at 10:20 AM Author Share Posted January 21, 2013 at 10:20 AM 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. Quote Link to comment Share on other sites More sharing options...
borg Posted January 21, 2013 at 11:21 AM Share Posted January 21, 2013 at 11:21 AM 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? Quote Link to comment Share on other sites More sharing options...
remotecontrol Posted January 21, 2013 at 11:57 AM Author Share Posted January 21, 2013 at 11:57 AM Bei ist ist die Kombination ein Industrial Quad Relay mit Java API. Quote Link to comment Share on other sites More sharing options...
borg Posted January 21, 2013 at 12:46 PM Share Posted January 21, 2013 at 12:46 PM 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. Quote Link to comment Share on other sites More sharing options...
remotecontrol Posted January 21, 2013 at 02:21 PM Author Share Posted January 21, 2013 at 02:21 PM 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). Quote Link to comment Share on other sites More sharing options...
remotecontrol Posted January 21, 2013 at 02:24 PM Author Share Posted January 21, 2013 at 02:24 PM Wichtiger Nachtrag (hatte ich vergessen zu testen): Der socket.setTcpNoDelay(true) behebt scheinbar das Problem! Dann laufen alle Requests in 5-6ms. Quote Link to comment Share on other sites More sharing options...
photron Posted January 21, 2013 at 02:39 PM Share Posted January 21, 2013 at 02:39 PM 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. Quote Link to comment Share on other sites More sharing options...
remotecontrol Posted January 21, 2013 at 02:53 PM Author Share Posted January 21, 2013 at 02:53 PM Kann ich machen, schaffe ich heute aber nicht mehr. Quote Link to comment Share on other sites More sharing options...
photron Posted January 25, 2013 at 08:52 AM Share Posted January 25, 2013 at 08:52 AM Alle 2.0 Bindings haben TCP_NODELAY aktiviert. Quote Link to comment Share on other sites More sharing options...
remotecontrol Posted January 25, 2013 at 06:22 PM Author Share Posted January 25, 2013 at 06:22 PM 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. Quote Link to comment Share on other sites More sharing options...
borg Posted January 25, 2013 at 06:48 PM Share Posted January 25, 2013 at 06:48 PM 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 . Auf jeden Fall vielen Dank für die Hilfe und das Testen! Quote Link to comment Share on other sites More sharing options...
AuronX Posted January 25, 2013 at 06:54 PM Share Posted January 25, 2013 at 06:54 PM Hmmm... bei meinem selbstfahrenden RC-Auto habe ich es damals darauf geschoben, dass mein ESC zu langsam reagiert hat... möglicherweise war der ja gar nicht schuld Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.