2016-02-01 10 views
5

Ich habe einen Roboter, der Steuercode mit Echtzeitpriorität auf einem PREEMPT-RT Patched Linux OS auf einem Beaglebone Black ausführt. Der gesamte Code ist in C geschrieben und läuft mit 500Hz.Latenzspitzen während der Datenprotokollierung in Echtzeit Embedded Linux

Ich habe bemerkt, Latenz im Bereich von ein paar hundert Millisekunden hin und wieder beim Ausführen des Codes und ich habe es auf die Datenprotokollierungsfunktion, die ich schrieb. Diese Latenz führt dazu, dass die Steuerung meines Roboters fehlschlägt, da ich abhängig von der Echtzeitfunktion viel habe.

Der relevante Teil des Codes ist unten. Ich habe eine Menge Code aus Gründen der Übersichtlichkeit geschnitten, aber ich werde diesen Beitrag bearbeiten, wenn etwas benötigt wird.

Ich muss Daten von mehreren Variablen (wahrscheinlich 20-50) mit einer guten Rate, vielleicht 100-125Hz protokollieren. Daten müssen nicht mit der Kontrollrate protokolliert werden (alle 2 ms), aber ich habe sie auf 12 ms verringert und sehe immer noch Latenzspitzen alle paar Minuten.

Die Latenz kann ein Problem mit dem fprintf Aufruf sein. Ist dies eine Einschränkung des BeagleBone Black, mein Code oder nur die Art der Datenprotokollierung?

Eine ähnliche Frage wurde hier gefragt, aber schien nicht mein Problem zu beheben: Finding latency issues (stalls) in embedded Linux systems

+1

Ein Nicht-TTY-Datei-Handle ist standardmäßig blockweise gepuffert. Nach dem "fprintf" von 4096 Bytes wird der Puffer auf den Datenträger geleert, was die Latenz verursachen kann. Können Sie die eigentliche Protokollierung nicht in einen separaten Thread auslagern? Queue logMessages und entnimmt sie in Ihrem Logthread. – Ctx

+0

Wird dieser Code als Teil eines normalen Prozesses ausgeführt? Steuert es Mutexe, Semaphore usw., die einen Gerätetreiber blockieren? – wallyk

+0

@jekso: Erstellen Sie einen Protokollierungs (p) -Thread und verwenden Sie so etwas wie eine doppelt verkettete Liste als Warteschlange (Enqueue am Kopf, entmutigen am Ende) und pthread_cond_wait/notify, um neue Einträge zu signalisieren. – Ctx

Antwort

2

fprintf zu verwenden ist eine große Zeitenke, insbesondere für R/T-Protokollierung. Loggen Sie sich binär ein und schreiben Sie ein Dienstprogramm, um es später auszudrucken.

Statt:

fprintf(file,"%.2f %.2f %.2f",data1,data2,data3); 

Do:

fwrite(&data1,sizeof(double),1,file); 
fwrite(&data2,sizeof(double),1,file); 
fwrite(&data3,sizeof(double),1,file); 

Noch besser:

struct data { 
    double data1; 
    double data2; 
    double data3; 
    time_t event_time; 
    ... 
}; 

struct data data; 

fwrite(&data,sizeof(struct data),1,file); 

Wenn es immer noch zu langsam ist, fügen Sie die Struktur an eine Ringwarteschlange und habe einen separaten Thread schreibe die Einträge aus.

Wenn die Plattenschreib nicht mit den [jetzt] Binärdaten Schritt halten kann, um die Ring-Warteschlange erhalten und nur die Warteschlange post-mortem-Dump, wenn Sie einen fatalen Fehler


auch erkennen, betrachten Verwenden Sie mmap, um auf die Datei beim Schreiben zuzugreifen. Siehe meine Antwort [mit Benchmarks] hier: read line by line in the most efficient way *platform specific*

+0

Dies wird das zugrunde liegende Problem nicht beheben, sondern seine Vorkommen nur um einen Faktor von 4 oder 10 verringern, aber es wird immer noch auftreten. Ein einfacherer Mechanismus, um dasselbe zu tun, ist das Aufrufen von [setvbuf() '] (http://man7.org/linux/man-pages/man3/setbuf.3.html) mit einem großen Puffer (wie 16 Megabyte) . – wallyk

+0

Vielen Dank für die Antwort. Also wäre "fwrite" von Natur aus schneller, obwohl es mitten in meinem Echtzeitprozess noch in eine Datei schreibt? Edit: Ich sah gerade walkyk's Kommentar oben und das war, worum ich besorgt war. Ich habe die Menge der Daten, die geschrieben werden, ein paar Mal verringert, und es hat nur die Häufigkeit der Latenzspitzen verringert, aber nicht vollständig eliminiert. – jekso

+0

Ja. 'fprintf' ist _sehr_langsam (z. B. 100x langsamer), insbesondere mit Fließkomma. Ich habe Produktions-R/T-Systeme mit ähnlichen Protokollierungsanforderungen ausgeliefert, daher spreche ich hier aus Erfahrung. Wenn nach dem Binärschreiben in Datei ändern, wenn es immer noch zu langsam ist, schreiben Sie die Daten in einen Speicherring Puffer und die letzten N-Einträge ausgeben, wenn Sie einen Fehler erkennen –