remotecontrol Geschrieben February 14, 2013 at 18:50 Geschrieben February 14, 2013 at 18:50 Hallo Admins, ich habe bei mir zwei Methoden der Device-Klasse wie folgt umgestellt: public boolean getResponseExpected(byte functionId) { // IPConnection.unsignedByte creates values from 0..255 only byte value = responseExpected[iPConnection.unsignedByte(functionId)]; if(value != RESPONSE_EXPECTED_FLAG_INVALID_FUNCTION_ID) { return value == RESPONSE_EXPECTED_FLAG_ALWAYS_TRUE || value == RESPONSE_EXPECTED_FLAG_TRUE; } throw new IllegalArgumentException("Invalid function ID " + functionId); } public void setResponseExpected(byte functionId, boolean responseExpected) { // IPConnection.unsignedByte creates values from 0..255 only int index = IPConnection.unsignedByte(functionId); byte value = this.responseExpected[index]; if(value == RESPONSE_EXPECTED_FLAG_INVALID_FUNCTION_ID) { throw new IllegalArgumentException("Invalid function ID " + functionId); } if(value == RESPONSE_EXPECTED_FLAG_ALWAYS_TRUE || value == RESPONSE_EXPECTED_FLAG_ALWAYS_FALSE) { throw new IllegalArgumentException("Response Expected flag cannot be changed for function ID " + functionId); } if(responseExpected) { this.responseExpected[index] = RESPONSE_EXPECTED_FLAG_TRUE; } else { this.responseExpected[index] = RESPONSE_EXPECTED_FLAG_FALSE; } } Hintergrund: IPConnection.unsignedByte() liefert korrekt nur 0..255 zurück (kein Range-Check notwendig)der Range-Check in Java erfolgte auf Basis der functionId und nicht anhand des berechneten Index und nachdem schon einmal ins Array zugegriffen wurde => bringt leider eh nichtsIPConnection.unsignedByte() ist ein echter Funktionsaufruf, darum speichere ich den Wert zwischen, damit die Funktion nicht zu oft aufgerufen wird. Gerade bei der Ansteuerung von Servos erfolgt viel Kommunikation und die Funktion getResponseExpected wird zig-tausendfach aufgerufen. In Summe bringt das ein paar % bei den Servoaufrufen. Auf CPU-schwächeren Systemen kann das hilfreich sein. Vielleicht übernehmt Ihr die Anpassung ins API. Zitieren
AuronX Geschrieben February 14, 2013 at 19:28 Geschrieben February 14, 2013 at 19:28 Du konntest dadurch messbare Geschwindigkeitsverbesserungen erzielen? Ich finde deinen Code besser lesbar (habe den getter mit dem Original verglichen), insofern würde ich in jedem Fall dazu raten deine Änderung zu übernehmen. Allerdings kann ich mir nicht vorstellen, dass in einem IO-lastigen System wie TF solche Mikro-Optimierungen messbar helfen. Oder übersehe ich hier etwas? Immerhin ist doch bei "viel" Servo Kommunikation insbesondere viel IO enthalten oder? Wenn ich bedenke, dass die Taktrate der Nachrichten zum Brick bei 1000 Hz liegt (1 ms), dann kann ich mir nicht vorstellen wie eine Optimierung im µs (oder gar ns?) Bereich Verbesserungen bringen kann. Zitieren
remotecontrol Geschrieben February 14, 2013 at 19:36 Autor Geschrieben February 14, 2013 at 19:36 Ein kleiner Test mit Aufrufen von getResponseExpected() in alter und neuer Variante hat bei mir OLD: 26163us NEW: 21645us ausgegeben, also gut 15%. Zitieren
AuronX Geschrieben February 14, 2013 at 19:52 Geschrieben February 14, 2013 at 19:52 Wie viele Aufrufe sind das jeweils insgesamt? (ich gehe davon aus, dass du sie in einer Schleife mehrfach gerufen hast) Was ich meine: Der bloße Aufruf der Funktion getResponseExpected() ist jetzt 15% schneller (weniger CPU-Zeit), insgesamt sind aber die ganzen TF-Funktionen eher IO-Bound und nicht CPU-Bound, das bedeutet, dass du zwar einige Takte auf der CPU sparst, aber die Kommunikation noch immer eine Millisekunde dauert. Ich überschlage das mal sehr grob: vorher: 1 ms + 1 µs = 1001 µs nachher: 1 ms + 0 µs = 1000 µs ------------------------------ Ersparnis: 1 µs (= 0.1%) edit: Ich will übrigens gar nicht meckern, ich finde es gut, wenn sich viele Leute den Code anschauen und verbessern. Ist also nicht böse gemeint. Ich befürchte aber, dass es verschenkte Mühe ist, wenn deine Motivation darin besteht die Performance zu verbessern. Zitieren
remotecontrol Geschrieben February 14, 2013 at 20:02 Autor Geschrieben February 14, 2013 at 20:02 Das mit der Gesamt-Zeit ist völlig korrekt: das spart nur 0.x% der Gesamtzeit ein. Ich hatte 100.000 Aurufe. edit: reale Performance-Verbesserung bringt das nicht - stimme ich zu. Bei Tablets gilt aber: CPU-Verbrauch kostet Akku. Darum suche ich gerade nach Optimierungen. Der Garbage-Collektor hat bei mir auch viel zu tun, wegen den Byte-Buffern ... edit: der Garbage-Collector bringt kleine Aussetzer rein und läuft bei mir schon alle 10 Sekunden. Noch eine Anmerkung zur IO bei Servos: Requests mit Response brauchen per WLAN bei mir ca. 5-6ms. Servo-Requests ohne Response liegen aber weit unter 1ms, auch per WLAN (so meine Messung). Real sende ich gut 100-120 Requests pro Sekunde, wenn ich mit je einem Finger in einem Kreuzfeld jeweils 2 Servos bewege (in Summe also 4 Servos quasi gleichzeitig). Zitieren
AuronX Geschrieben February 14, 2013 at 20:57 Geschrieben February 14, 2013 at 20:57 Das mit dem GC ist ja echt bedenklich ^^ Müsste man glatt mal schauen, ob die Bindings in dieser Hinsicht auch sparsam mit den Ressourcen des Geräts umgehen. Habe bisher nicht so sehr auf das Speicherverhalten geachtet (und wenn überhaupt nur die C#-Bindings reviewt), aber ich glaube das wäre nochmal einen Blick wert ^^ Zitieren
photron Geschrieben February 15, 2013 at 09:54 Geschrieben February 15, 2013 at 09:54 Richtig, getResponseExpected mach unnötige viele Funktionsaufrufe. Ich bin gerade dabei das in Java zu verbessern und schau mir dann auch noch alle anderen Bindings an. Zitieren
photron Geschrieben February 27, 2013 at 09:12 Geschrieben February 27, 2013 at 09:12 Ist seit Java Bindings 2.0.4 verbessert. Im gleichen Zuge habe ich auch den Response Expected Code der anderen Bindings überarbeitet. Zitieren
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.