Ring buffer overflows/drops - langsamer client fuehrt zu drops bei aufnahmen

  • vdr 2.2.0 "schneller" Server (E3-1231 CPU, SATA3,..) mit 5 tunern (FF+4*DDbridge), streamdev-server 0.6.1.


    Aufzeichnen von eg: 10 * SD Kanaelen verteilt auf die 5 tuner - keine Probleme.


    Aufzeichnen von nur einem Sender. Natuerlich auch kein Problem
    Gleichzeitig streamen desselben senders per streamdev auf zu langsamen client: Aufnahme hat paketverluste.


    Siehe Auszuege aus Syslog am Ende. Wenn ich das richtig interpretiere passieren die drops im "device section handler thread" und im "device receiver thread", die ja wohl irgendwie beide im Datenpfad fuer die Aufzeichnung sind.


    Das war jetzt getested einfach mit VDR streamdev receiver mit PS oder TS format uebers (viel zu langsame) Internet, weswegen da natuerlich der streamdev nie alle pakete abliefern kann. In der Realitaet ist das Problem ein RPI1 hinter powerline und dann wohl alle arten von temporaeren Powerline durchsatzproblemen. Aber zu langsame clients muss ja auf jeden Fall gehen ohne dass dabei gleichzeitig passierende Aufnahmen kaputt gehen. Temporaere Durchsatprobleme zu clients kann man ja nie komplett vermeiden bei billigclients, wifi oder powerline oder streaming uebers internet.


    Lokal kann man das problem einfach dadurch reproduzieren indem man als 2te zeile in externremux.sh sowas wie ein "sleep 10000" reinkloppt, und dann eg: via VLC /EXT/<kanal> stream. Da kommt beim VLC natuerlich nix mehr an, aber der streamdev verhaelt sich in Richtung VDR genauso wie ein zu langsamer client - er nimmt keine daten vom VDR mehr ab, und im VDR kommt es zum head-of-line blocking der gesharten device/receiver threads.


    Problem ist nicht FF spezifisch (device 1), auch repliziert mit ddbridge (octopus) tuner. Problem tritt auch auf wenn der langsam gestreamte Kanal nicht derselbe ist wie der aufgenommene, sondern bloss auf dem selben transponder/tuner ist - eg: streamen von KIKA bei gleichzeitiger Aufnahme von ZDF.



    01:25:12 vdr[14597]: [14623] device 1 section handler thread started (pid=14597, tid=14623, prio=low)
    ...
    01:25:14 vdr[14597]: [14597] recording to '.../Wilsberg/Die_Entf?hrung/2016-12-07.23.54.28-0.rec/00003.ts'
    01:25:14 vdr[14597]: [14671] recording thread started (pid=14597, tid=14671, prio=high)
    01:25:14 vdr[14597]: [14672] device 1 receiver thread started (pid=14597, tid=14672, prio=high)
    01:25:14 vdr[14597]: [14673] device 1 TS buffer thread started (pid=14597, tid=14673, prio=high)
    ...
    01:26:21 vdr[14597]: [14641] Streamdev: Accepted new client (HTTP) 192.168.124.201:51359
    01:26:22 vdr[14597]: [14883] streamdev-writer thread started (pid=14597, tid=14883, prio=high)
    01:26:22 vdr[14597]: [14884] streamdev-livestreaming thread started (pid=14597, tid=14884, prio=high)
    ...
    01:26:26 vdr[14597]: [14623] ERROR: 1 ring buffer overflow (188 bytes dropped)
    01:26:28 vdr[14597]: [14672] ERROR: 1 ring buffer overflow (188 bytes dropped)
    01:26:32 vdr[14597]: [14623] ERROR: 57 ring buffer overflows (10716 bytes dropped)
    01:26:34 vdr[14597]: [14672] ERROR: 35027 ring buffer overflows (6585076 bytes dropped)
    01:26:38 vdr[14597]: [14623] ERROR: 60 ring buffer overflows (11280 bytes dropped)
    01:26:40 vdr[14597]: [14672] ERROR: 38349 ring buffer overflows (7209612 bytes dropped)
    01:26:44 vdr[14597]: [14623] ERROR: 61 ring buffer overflows (11468 bytes dropped)
    01:26:46 vdr[14597]: [14672] ERROR: 39070 ring buffer overflows (7345160 bytes dropped)

  • Die Verteilung der TS-Pakete auf die einzelnen cReceiver ist eine sehr zentrale und zeitkritische Stelle. Alles hier läuft in "Echtzeit" ab. Ein cReceiver *muss* in seiner Receive()-Funktion das Paket sofort annehmen und ohne unnötige Verzögerung zurückkehren. Wenn er das nicht garantieren kann, dann hat er ein Problem. Eventuell muß er die erhaltenen Pakete in einem eigenen Ringbuffer zwischenspeichern (der ihm dann natürlich überlaufen kann, wenn er selber sie nicht schnell genug weiterverarbeiten kann; das hätte dann aber keine Auswirkungen auf laufende Aufnahmen - vorausgesetzt die gesamte CPU-Leistung reicht aus).
    Ich würde also zunächst mal annehmen, daß das Problem im streamdev-Server liegt und dieser nicht schnell genug aus seiner Receive()-Funktion zurückkehrt (und damit "den ganzen Betrieb aufhält" ;-).


    Klaus

  • Danke, Klaus


    So eine Antwort habe ich befuerchtet ;( Mit diesem Design schuetzt der VDR halt nicht die Aufnahmen vor schlecht geschriebenen plugins. Und jeder plugin entwickler hat die Herausforderung einen komplett asynchronen Datenempfangsteil zu schreiben. statt das es dafuer einmal im VDR code gibt der halt in der lage ist pro plugin daten speichern und notfalls pro plugin wegschmeissen zu koennen. Erinnert an MacOS < 10 collaborative multitasking ;-)) Oder SVDRP. Aber da wird das problem ja im VDR core in 2.3 gefixt.


    Meine Befuerchtung ist jetzt halt, dass es so ein bufferdesign im streamdev-server nicht gibt, und das es da fuers streamdev nicht mehr genug aktive Entwicklung gibt dass das da in absehbarer Zeit reinkommt.


    Ansonsten faellt mir als kurzfristiger workaround noch eine art Notbremse ein: wenn die receive funktion fuer ein plugin feststellen kann wie hoch der fuellstand im VDR core buffer ist, dann koennte es einfach die empfangenen daten ab einem bestimmten konfigurierten threshold (< 100%!) direkt wegschmeissen statt rauszusenden. Wenn man das auf der plugin seite implementieren will, dann muss man natuerlich einen API call haben um den fuellstand zu erfragen. Gibts so einen API call ?


    Das notbremsen Design hoert sich dumm an, weil man ja garnicht genau weiss das dieses plugin wirklich der schudige fuer den hohen gemeinsamen bufferstand ist, aber das ist genau das was in Routern beim QoS bei gemeinsamer Queue gemacht wird (per class drop thresholds). Tut statistisch erstaunlich gut. Je verdaechtiger ein plugin ist sich schlecht zu verhalten, desto niedriger muss bloss sein drop threshold sein.

  • Meine Befuerchtung ist jetzt halt, dass es so ein bufferdesign im streamdev-server nicht gibt...

    Das konnte ich mir nicht vorstellen und ist wohl auch nicht so.


    So wie es aussieht schreibt die Receive()-Funktion die Daten direkt in einen Ringbuffer und beendet sofort, wenn der Puffer schon voll ist.
    livestreamer.c Zeile 566ff.

    Gruss
    SHF


Jetzt mitmachen!

Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!