[pulseaudio-discuss] [PATCH 0/2] Improve default buffer latency parameters
David Henningsson
david.henningsson at canonical.com
Tue Mar 19 05:51:55 PDT 2013
I spend some of yesterday and today investigating our different buffer
modes to see how they behave in practice, i e when PulseAudio asks for
more data and what the resulting latency will be.
Our buffer modes are
* "adjust latency mode" / PA_STREAM_ADJUST_LATENCY,
* "traditional mode" / PA_STREAM_NOFLAGS,
* "early requests mode" / PA_STREAM_EARLY_REQUESTS.
All tests were done on my onboard soundcard, which has 64K of maximum hardware buffer,
which translates to 371 ms in the chosen sample format.
When reading this, allow a margin of 1-2 ms for various system latencies, including
the turn-around time of the "Stream started" notification, and also remember the
default process_msec of 20 ms.
The first test - high latency scenario, I had all buffer_attr parameters set to -1.
PA_STREAM_ADJUST_LATENCY:
7.19: Writing 1628.50 ms, latency 0.00 to 1628.50 ms
10.88: Stream started
10.96: Writing 363.74 ms, latency 1628.42 to 1992.16 ms
363.12: Writing 358.25 ms, latency 1640.00 to 1998.26 ms
715.59: Writing 352.83 ms, latency 1645.79 to 1998.62 ms
PA_STREAM_NOFLAGS:
1.35: Writing 2000.00 ms, latency 0.00 to 2000.00 ms
2.70: Stream started
2.72: Writing 370.07 ms, latency 1999.98 to 2370.05 ms
355.11: Writing 351.75 ms, latency 2017.66 to 2369.41 ms
706.85: Writing 351.84 ms, latency 2017.67 to 2369.50 ms
PA_STREAM_EARLY_REQUESTS:
11.67: Writing 2000.00 ms, latency 0.00 to 2000.00 ms
15.24: Stream started
25.53: Writing 29.02 ms, latency 1989.71 to 2018.73 ms
46.16: Writing 20.61 ms, latency 1998.10 to 2018.72 ms
66.90: Writing 20.63 ms, latency 1997.98 to 2018.62 ms
To sum up:
PA_STREAM_ADJUST_LATENCY - Every time latency is below 2000 - 371 + 20 ms,
we're asked to fill up to 2000 ms.
PA_STREAM_NOFLAGS - Every time latency is below 2000 + 20 ms,
we're asked to fill up to 2000 + 371 ms.
PA_STREAM_EARLY_REQUESTS - Every time latency is below 2000 ms,
we're asked to fill up to 2000 + 20 ms.
Side note: for both PA_STREAM_ADJUST_LATENCY and PA_STREAM_NOFLAGS, after a while
the write request is split, like this:
1771.19: Writing 221.90 ms, latency 2018.19 to 2240.09 ms
1771.55: Writing 130.27 ms, latency 2239.73 to 2370.00 ms
2122.88: Writing 90.48 ms, latency 2018.67 to 2109.15 ms
2123.12: Writing 149.43 ms, latency 2108.91 to 2258.35 ms
2123.35: Writing 111.93 ms, latency 2258.11 to 2370.04 ms
The sum is the same, and it's nothing a well written client shouldn't be able to handle,
but it sounds like there is some room for optimisation here. I haven't looked into why
this could be.
Ok, second test, a medium-latency scenario, where we set tlength = 200 ms, which IIRC
is the GStreamer default.
PA_STREAM_ADJUST_LATENCY:
8.29: Writing 120.00 ms, latency 0.00 to 120.00 ms
9.98: Stream started
10.06: Writing 78.71 ms, latency 119.92 to 198.63 ms
70.17: Writing 60.32 ms, latency 138.52 to 198.84 ms
130.06: Writing 60.23 ms, latency 138.95 to 199.17 ms
PA_STREAM_NOFLAGS:
9.01: Writing 200.00 ms, latency 0.00 to 200.00 ms
10.68: Stream started
10.77: Writing 158.71 ms, latency 199.90 to 358.61 ms
151.09: Writing 140.29 ms, latency 218.29 to 358.59 ms
291.38: Writing 140.29 ms, latency 218.30 to 358.59 ms
PA_STREAM_EARLY_REQUESTS:
7.51: Writing 200.00 ms, latency 0.00 to 200.00 ms
9.07: Stream started
19.45: Writing 28.98 ms, latency 189.62 to 218.60 ms
39.67: Writing 20.36 ms, latency 198.38 to 218.74 ms
60.50: Writing 20.52 ms, latency 197.91 to 218.43 ms
To sum up:
PA_STREAM_ADJUST_LATENCY - Every time latency is below 200 / 2 + 2 * 20 ms = 140 ms,
we're asked to fill up to 200 ms.
PA_STREAM_NOFLAGS - Every time latency is below 200 + 20 ms,
we're asked to fill up to 200 * 2 - 2 * 20 ms = 360 ms.
PA_STREAM_EARLY_REQUESTS - Every time latency is below 200 ms,
we're asked to fill up to 200 + 20 ms.
The 2 * minreq thing used in the core isn't entirely obvious to me,
but the general rule remain; if you want *max* latency to be tlength,
set PA_STREAM_ADJUST_LATENCY, and if you want *min* latency to be tlength,
go for PA_STREAM_NOFLAGS.
PA_STREAM_EARLY_REQUESTS is probably only meant where you specify minreq too,
like the alsa-plugins layer does. Let's leave that for now.
Ok, next is a low-latency scenario of setting maxlength = tlength = 10 ms.
But it failed miserably in all buffer modes, because PulseAudio wouldn't ask
for more data soon enough.
With patch 2/2 in this series applied, things got a lot better:
PA_STREAM_ADJUST_LATENCY:
7.52: Writing 7.50 ms, latency 0.00 to 7.50 ms
8.55: Stream started
10.11: Writing 2.72 ms, latency 5.95 to 8.67 ms
14.21: Writing 3.88 ms, latency 4.56 to 8.44 ms
17.88: Writing 3.83 ms, latency 4.77 to 8.60 ms
PA_STREAM_NOFLAGS:
8.40: Writing 10.00 ms, latency 0.00 to 10.00 ms
9.80: Stream started
9.87: Writing 3.70 ms, latency 9.94 to 13.63 ms
12.33: Writing 2.77 ms, latency 11.16 to 13.93 ms
15.04: Writing 2.72 ms, latency 11.22 to 13.94 ms
PA_STREAM_EARLY_REQUESTS:
7.18: Writing 10.00 ms, latency 0.00 to 10.00 ms
8.15: Stream started
9.58: Writing 2.65 ms, latency 8.57 to 11.22 ms
13.27: Writing 3.72 ms, latency 7.54 to 11.26 ms
17.06: Writing 3.74 ms, latency 7.46 to 11.21 ms
With the minreq patch that sets minreq to 10 / 4 = 2.5 ms, we can see that the result
for PA_STREAM_ADJUST_LATENCY is to try to keep the latency between 7.5 ms and 10 ms,
for PA_STREAM_NOFLAGS to try to keep the latency between 12.5 ms and 15 ms, and
for PA_STREAM_EARLY_REQUESTS to try to keep latency between 10 ms and 12.5 ms.
We end up always writing a little bit more than 2.5 ms in all scenarios, probably due to
scheduling variations within the system.
Comments / questions?
David Henningsson (2):
protocol-native: Ensure tlength is not set higher than maxlength
protocol-native: Lower default minreq in low-latency scenarios
src/pulsecore/protocol-native.c | 13 ++++++++++---
1 file changed, 10 insertions(+), 3 deletions(-)
--
1.7.9.5
More information about the pulseaudio-discuss
mailing list