alsa: Avoid creating tiny memchunks on write iterations

If the ALSA device supports granular pointer reporting, we end up in a
situation where we write out a bunch of data, iterate, and then find a
small amount of data available in the buffer (consumed while we were
writing data into the available buffer space). We do this 10 times
before quitting the write loop.

This is inefficient in itself, but can also have wider consequences. For
example, with module-combine-sink, this will end up pushing the same
small chunks to all other devices too.

Given both of these, it just makes sense to not try to write out data
unless a minimum threshold is available. This could potentially be a
fragment, but it's likely most robust to just work with a fraction of
the total available buffer size.
This commit is contained in:
Arun Raghavan 2017-02-28 10:45:25 +05:30
parent 2898a5188c
commit c82e4913e8

View file

@ -88,6 +88,8 @@
#define DEFAULT_REWIND_SAFEGUARD_BYTES (256U) /* 1.33ms @48kHz, we'll never rewind less than this */ #define DEFAULT_REWIND_SAFEGUARD_BYTES (256U) /* 1.33ms @48kHz, we'll never rewind less than this */
#define DEFAULT_REWIND_SAFEGUARD_USEC (1330) /* 1.33ms, depending on channels/rate/sample we may rewind more than 256 above */ #define DEFAULT_REWIND_SAFEGUARD_USEC (1330) /* 1.33ms, depending on channels/rate/sample we may rewind more than 256 above */
#define DEFAULT_WRITE_ITERATION_THRESHOLD 0.03 /* don't iterate write if < 3% of the buffer is available */
struct userdata { struct userdata {
pa_core *core; pa_core *core;
pa_module *module; pa_module *module;
@ -580,11 +582,18 @@ static int mmap_write(struct userdata *u, pa_usec_t *sleep_usec, bool polled, bo
break; break;
} }
if (++j > 10) { j++;
if (j > 10) {
#ifdef DEBUG_TIMING #ifdef DEBUG_TIMING
pa_log_debug("Not filling up, because already too many iterations."); pa_log_debug("Not filling up, because already too many iterations.");
#endif #endif
break;
} else if (j >= 2 && (n_bytes < (DEFAULT_WRITE_ITERATION_THRESHOLD * (u->hwbuf_size - u->hwbuf_unused)))) {
#ifdef DEBUG_TIMING
pa_log_debug("Not filling up, because <%g%% available.", DEFAULT_WRITE_ITERATION_THRESHOLD * 100);
#endif
break; break;
} }
@ -754,11 +763,18 @@ static int unix_write(struct userdata *u, pa_usec_t *sleep_usec, bool polled, bo
break; break;
} }
if (++j > 10) { j++;
if (j > 10) {
#ifdef DEBUG_TIMING #ifdef DEBUG_TIMING
pa_log_debug("Not filling up, because already too many iterations."); pa_log_debug("Not filling up, because already too many iterations.");
#endif #endif
break;
} else if (j >= 2 && (n_bytes < (DEFAULT_WRITE_ITERATION_THRESHOLD * (u->hwbuf_size - u->hwbuf_unused)))) {
#ifdef DEBUG_TIMING
pa_log_debug("Not filling up, because <%g%% available.", DEFAULT_WRITE_ITERATION_THRESHOLD * 100);
#endif
break; break;
} }