Blog

Niedrige Latenz beim Game-Streaming, wenn das Spiel die GPU auslastet

Der schwierigste Fall für jeden Streaming-Host ist der wichtigste: ein forderndes Spiel, das die GPU bereits auslastet. Warum der Encoder am Ende wartet — und die zwei Hebel, die unsere Encode-Zeit von ~30 ms auf ~4 ms gebracht haben.

Führt man einen Streaming-Benchmark auf einem leeren Desktop aus, sieht fast alles schnell aus. Der Fall, auf den es ankommt, ist der schwierige: Du streamst ein anspruchsvolles Spiel, das die GPU bereits auf 100 % auslastet. Genau da brechen die meisten Setups ein — die Bildrate kollabiert und die Latenz schießt hoch, obwohl direkt daneben ein eigener Video-Encoder in der GPU sitzt.

Der Encoder ist nicht der Flaschenhals — die Warteschlange davor ist es

Es liegt nahe, dem Encoder die Schuld zu geben. Aber auf einer modernen GPU ist NVENC (oder das Pendant von AMD und Intel) ein separater Hardware-Block, der kaum ausgelastet ist. Das eigentliche Problem ist das Scheduling: Unsere Capture-und-Encode-Arbeit muss auf der GPU drankommen, und wenn ein Spiel sie auslastet, wird sie immer wieder nach hinten geschoben. Der Encoder steht still und wartet auf einen Kontextwechsel, den das Spiel ständig für sich entscheidet. Auf unserem RTX-4090-Testhost stieg die Encode-Zeit unter einem fordernden Spiel auf rund 30 ms — während der Encoder selbst fast nichts tat.

Hebel 1: Echtzeit-Priorität auf der GPU anfordern

Der erste Fix: aufhören, eine höfliche Hintergrundaufgabe zu sein. punktfunk fordert für seinen Capture-und-Encode-Kontext Echtzeit-Scheduling-Priorität auf der GPU an, sodass er die Arbeit des Spiels verdrängt, statt sich dahinter anzustellen — und der Encoder kommt zügig dran. Auf demselben Host sank die Encode-Zeit allein dadurch von etwa 35 ms auf etwa 15 ms — ohne sichtbare Kosten fürs Spiel.

Hebel 2: die Frame-Warteschlange genau ein Bild tief halten

Beim zweiten Fix geht es um Aktualität. Puffert das virtuelle Display mehrere Frames, bevor der Encoder eines abholt, ist jedes davon schon veraltet, wenn es bei dir ankommt. punktfunk hält diese Warteschlange nur ein Bild tief: immer das neueste Frame nehmen, nie einen Rückstau. Für sich genommen bringt das wenig, solange der Encoder wartet — aber sobald die Echtzeit-Priorität diese Wartezeit verkürzt, ist eine flache Warteschlange ein großer Latenzgewinn. In Doom: The Dark Ages brachte das unseren End-to-End-Encode-Pfad von etwa 17,5 ms auf etwa 4,4 ms und hob die einzigartigen (nicht wiederholten) Frames von 85 auf 129 pro Sekunde.

Das kombinierte Ergebnis

Zusammengenommen auf dem RTX-4090-Host und unter wirklich feindseliger Last — Counter-Strike 2 und Doom: The Dark Ages, die beide die GPU auslasten — ging derselbe Stream von rund 30 ms und 40-50 fps auf etwa 4 ms Encode-Zeit und 130-148 einzigartige Frames pro Sekunde. Das Spiel läuft weiter; der Stream verliert nur den Kampf um die GPU nicht mehr.

Noch ein Detail: dem Encoder das Format geben, das er will

Es gibt eine verwandte Falle: Übergibt man dem Encoder volle RGB-Frames, erzwingt das eine Farbraum-Konvertierung auf genau den GPU-Kernen, die das Spiel auslastet. Füttert man die Video-Engine stattdessen mit NV12 (oder P010 für HDR), bleibt diese Arbeit von den Shadern fern. Es ist nicht der entscheidende Latenzhebel, aber auf einer ausgelasteten GPU hilft jede vermiedene Shader-Arbeit.

Warum das wichtig ist

Der ganze Sinn von Game-Streaming ist es, anspruchsvolle Spiele zu spielen — der Host steht also immer unter Last. Ein Streaming-Host muss sich auf einer ausgelasteten GPU rücksichtsvoll verhalten und trotzdem seinen Platz behaupten — und das richtig hinzubekommen ist der Unterschied zwischen „auf dem Desktop okay“ und „auch unter Volllast noch 4 ms“. Den größeren Zusammenhang gibt es in wie punktfunk im Vergleich zu Sunshine + Moonlight abschneidet.