Service crackle fix: un-throttle the process while streaming (PerformanceMode)
The send-only service sounded hideous/crackly vs the main app, even standalone, with clean capture (capPeak ~0.44) and clean receiver metrics (no underruns/drops/gaps) -- the fingerprint of a process being starved by the OS scheduler, not a data problem. Cause: a headless Windows SERVICE is a background process, so Windows aggressively downclocks it (EcoQoS), migrates its threads onto efficiency cores, and gives it a coarse scheduler quantum -- exactly what starves the audio send loop into crackling. The interactive app engages PerformanceMode only on the user high-priority toggle; the service never engaged it at all, and being a service it is throttled far harder. Fix: the service now engages PerformanceMode (EcoQoS opt-out, High priority, 1ms timer, no deep C-states, working-set floor) whenever it is streaming, released on suspend/ dispose. Unconditional -- the service has no foreground/battery use case; it exists solely to stream and must not be throttled. Gate: 39/39. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
cd9760d7d5
commit
ec149ed09e
@@ -348,6 +348,14 @@ public sealed class ServiceSendHost : IDisposable
|
||||
// blind push. Same well-known audio port and the same components the interactive app uses.
|
||||
presence.Start(RemPacket.DefaultPort, endpoints);
|
||||
running = true;
|
||||
// Un-throttle the process while streaming. A headless Windows SERVICE is treated by the OS as a
|
||||
// background process and gets aggressively downclocked (EcoQoS), migrated onto efficiency cores
|
||||
// and given a coarse scheduler quantum — which starves the send loop and makes the stream
|
||||
// CRACKLE even though capture and the network look clean. The interactive app only does this on
|
||||
// the user's opt-in "high priority" toggle, but the service has no foreground/battery use case
|
||||
// (it exists solely to stream), so it always engages while sending. Idempotent; released in
|
||||
// Suspend. This is the fix for "the service sounds hideous vs the main app".
|
||||
try { PerformanceMode.Apply(true, msg => log?.Invoke($"service: {msg}")); } catch { /* best-effort */ }
|
||||
log?.Invoke($"service: streaming \"{profile.Title}\" — {specs.Count} source(s) to {endpoints.Count} peer(s)");
|
||||
return true;
|
||||
}
|
||||
@@ -366,6 +374,7 @@ public sealed class ServiceSendHost : IDisposable
|
||||
SwapMeterDevices(Array.Empty<CaptureSourceSpec>()); // release the endpoint-meter readers
|
||||
try { sessionKick?.Dispose(); } catch { /* ignore */ }
|
||||
sessionKick = null;
|
||||
try { PerformanceMode.Apply(false, msg => log?.Invoke($"service: {msg}")); } catch { /* best-effort */ }
|
||||
running = false;
|
||||
log?.Invoke("service: suspended (interactive app present)");
|
||||
}
|
||||
@@ -607,6 +616,7 @@ public sealed class ServiceSendHost : IDisposable
|
||||
try { deviceNotifier?.Dispose(); } catch { } deviceNotifier = null;
|
||||
try { sessionKick?.Dispose(); } catch { } sessionKick = null;
|
||||
SwapMeterDevices(Array.Empty<CaptureSourceSpec>());
|
||||
try { PerformanceMode.Apply(false); } catch { }
|
||||
try { presence.Dispose(); } catch { }
|
||||
try { sender.Stop(); } catch { }
|
||||
try { sender.Dispose(); } catch { }
|
||||
|
||||
Reference in New Issue
Block a user