perf(live): Debounce 600 ms, Sync-Versionen nur noch 5 Minuten (D79)

Gemeldet: ~3 s Verzoegerung zwischen zwei Browsern. Zerlegt statt geraten -
von 1,73 s gemessenem Weg A->B entfallen 1,67 s auf die Wartezeit vor dem
Senden. Alles andere sind zusammen ~70 ms.

Zwei Verdaechtige sind freigesprochen: Der Server weckt den wartenden Feed
39 ms nach dem PATCH (isoliert per curl, ohne Browser), und der Apache der
produktiven Instanz haelt den Long-Poll die vollen 25 s durch und schliesst
sauber mit 204 - kein Fenster ohne offenen Feed, kein 5-Sekunden-Fehlerpfad.
Produktiv kommen ~130 ms Rundlauf je Anfrage dazu.

Der Debounce bleibt ein Debounce (kein Takt): Wer durchtippt, erzeugt
weiterhin keine Version. Der Grund fuer die 1,5 s stammte aus der
Rate-Limit-Disziplin des Etherpad-Konzepts - und Etherpad ist ausgebaut (D78).

Die Aufbewahrung zahlt die haeufigeren Pushes: Jede Version speichert den
ganzen Text, und die Frist entscheidet einzig, ob ein zurueckgefallener Client
ein Diff oder den Volltext bekommt. Nutzersichtbar sind die Meilensteine, und
die werden nie verdichtet; zurueckfallen kann nur ein ruhender Feed
(Hintergrund-Tab). Zusammen sinkt die Spitze je aktiv getipptem Dokument von
115 MB auf 24 MB (49-kB-Plan, Dauertippen).

Dabei gefunden: Eine Schreibpause laenger als die Frist war mit einer Stunde
der Ausnahmefall und ist mit fuenf Minuten der Normalfall. Dass die letzte
Sync-Version davor nicht verlorengeht, haengt allein daran, dass
recordHistory() zuerst befoerdert und danach verdichtet - sonst loeschte die
Verdichtung genau den Stand, den die Befoerderung gleich zum Meilenstein
gemacht haette. Die Reihenfolge hat jetzt eine Zusicherung; vertauscht faellt
genau der danach benannte Test.

Werkzeuggrenze notiert: Der Automatisierungs-Browser zeigt seine Flaeche nicht
an, Chrome drosselt Timer verborgener Seiten auf 1 Hz (gemessen: ein blanker
setTimeout(600) feuert nach 999-1053 ms). Ein Sub-Sekunden-Debounce ist dort
grundsaetzlich nicht messbar.

501 Frontend-Tests, 139 Backend-Tests.
This commit is contained in:
mhoennig
2026-08-26 20:53:02 +02:00
parent bfacbe96e5
commit 627f6feca8
11 changed files with 140 additions and 13 deletions
+2 -1
View File
@@ -117,7 +117,8 @@ verworfene Elemente. Quelle sind ES-Module unter `src/`; `index.html` ist der
- **Server-Dokumente (`?live=`, D76):** `live.js` hält die entscheidbare Hälfte
(Adressen, Zeilen-Diff, Rebasen, Cursor-Rechnung, Feed-Regel), `app.js` die
Verdrahtung: `loadLive()` holt Text und Version und merkt beides als
**Schattenkopie**, `scheduleLivePush()` schickt nach 1,5 s Ruhe das Diff,
**Schattenkopie**, `scheduleLivePush()` schickt nach 0,6 s Ruhe das Diff
(D79 — die Wartezeit IST die gefuehlte Verzoegerung),
`runFeed()` hält einen Abruf offen (nur im sichtbaren Tab), `putOnServer()`
legt das aktive Dokument an („Auf den Server legen"). Die Basis-Adresse
bestimmt `serverBase()` (live.js): `?server=` vor dem offenen Dokument vor
+9 -4
View File
@@ -4316,7 +4316,7 @@ async function loadRemoteSource(){
wirklich, entscheidet der Mensch (Konflikt-Band unten). Alles andere
verschiebt der Server selbst. */
const LIVE_PARAM = 'live';
const LIVE_DEBOUNCE_MS = 1500; /* Ruhe vor dem Senden; D76 */
const LIVE_DEBOUNCE_MS = 600; /* Ruhe vor dem Senden; D76, D79 */
const LIVE_WAIT_S = 25; /* Wartezeit des Feeds; der Server klemmt sie ohnehin */
const LIVE_RETRY_MS = 5000; /* nach einem Netzfehler, bevor der Feed erneut fragt */
@@ -4423,9 +4423,14 @@ function adoptLive(doc){
/* ---------- Hinschicken ---------- */
/* Nach jeder Eingabe neu gestartet: Gesendet wird erst, wenn 1,5 s Ruhe ist.
Ohne den Takt entstünde je Tastendruck eine Version die Historie wäre ein
Transaktionslog, und das Netz hätte zu tun. */
/* Nach jeder Eingabe neu gestartet: Gesendet wird erst, wenn es 600 ms ruhig
ist. Ohne den Takt entstünde je Tastendruck eine Version die Historie wäre
ein Transaktionslog, und das Netz hätte zu tun.
Die Wartezeit **ist** die gefühlte Verzögerung: Gemessen braucht der Weg vom
Tastendruck bis zum Text des anderen 1,73 s, davon 1,67 s hier der Server
weckt den wartenden Feed 39 ms nach dem PATCH (D79). Sie bleibt ein
Debounce, kein Takt: Wer durchtippt, erzeugt weiterhin keine Version. */
function scheduleLivePush(){
if(!liveActive() || liveConflict) return;
if(liveState.pushTimer) clearTimeout(liveState.pushTimer);