After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 698960 - High CPU load with alsa
High CPU load with alsa
Status: RESOLVED NOTABUG
Product: GStreamer
Classification: Platform
Component: gst-plugins-base
1.0.6
Other Linux
: Normal normal
: git master
Assigned To: GStreamer Maintainers
GStreamer Maintainers
Depends on:
Blocks:
 
 
Reported: 2013-04-26 15:15 UTC by Paul HENRYS
Modified: 2013-05-28 08:09 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
Patch (10.88 KB, patch)
2013-04-26 15:15 UTC, Paul HENRYS
needs-work Details | Review
Patch (10.64 KB, patch)
2013-05-12 17:27 UTC, Paul HENRYS
rejected Details | Review

Description Paul HENRYS 2013-04-26 15:15:05 UTC
Created attachment 242584 [details] [review]
Patch

On an embedded board with an ARMv7 processor, I notice high CPU load from time to time using such a pipeline:

alsasrc ! audioconvert ! rtpL16pay ! udpsink

This can also be noticed with such simple pipeline (but less obvious):

alsasrc ! fakesink

After further investigation, I noticed that in applications using alsa-lib (e.g.: arecord, aplay, csound (http://www.csounds.com/manual/html/UsingRealTime.html)), if not set manually, buffer_size and period_size are a power of 2. And indeed, after applying such a constraint, the load peak disappeared. The "funny" thing is that without being a power of 2, I had a really low CPU load and sometime for a certain time a very high load, then having a power of 2 averaged the load. But the buffers were always passing through, there was no burst of buffers which would explained such a high load.
I also made the test using arecord and aplay and setting buffer_size and period_size to something not a power of 2 and the high CPU load appeared also.
FYI, I did not notice high CPU load on a multi-core processor but that probably hidden by the power of such a processor.

In the patch provided in attachment, as alsasrc/sink derived from audiobasesrc/sink indirectly, and these structures only allow to set the buffer_time and period_time. It calculates in alsasrc/sink the buffer_size and period_size from the buffer_time and period_time and round up to the next power of 2.

Any comments?

Cheers
Comment 1 Sebastian Dröge (slomo) 2013-04-29 08:33:50 UTC
Review of attachment 242584 [details] [review]:

I'm not sure of the general implications of always rounding up to the next power of 2 for platforms where this doesn't make a real difference. Also maybe we should instead round to the nearest power of two?

::: ext/alsa/gstalsa.c
@@ +659,3 @@
+/*
+ * Round up to the next highest power of 2
+ * From "Hacker's Delight", Henry S. Warren, Jr.'s

Nice trick, I didn't know this one yet :)

::: ext/alsa/gstalsasink.c
@@ -429,3 @@
-  period_time = alsa->period_time;
-
-retry:

With your changes we never retry if setting one of these fails and instead just error out. Doesn't seem optimal

@@ +475,3 @@
+  /* now try to configure the buffer size and period size */
+  if (alsa->buffer_time != -1 && !alsa->iec958) {
+    alsa->buffer_size = alsa->buffer_time / 1e6 * alsa->rate;

Use gst_util_uint64_scale() or the _int() variant of this here, and instead of 1e6 use GST_MSECOND.
Comment 2 Paul HENRYS 2013-04-29 09:40:37 UTC
I'll make the changes you suggested about the nearest power of 2, the retry and GST_MSECOND and I will provide a new patch. Then, we will see about the relevance to provide such a patch for any platform.
Thx for your feedback.
Comment 3 Paul HENRYS 2013-05-12 17:27:14 UTC
Ok in the new patch in attachment I did the changes advised. Then, I don't know if this is relevant for all architectures but it seems, as written above, that most of the time, buffer size and period size are a power of 2.

Something else that I noticed lastly is that the way the ring buffer is used in gstaudiobasesink and in Alsa lib is different. If I am not wrong, the number of segments in the ring buffer in audiobasesink should be kept low to minimize the latency. On the contrary in Alsa lib, the ring buffer is kept as full as possible: "ALSA will endeavor to keep the buffer as full as possible" (http://www.alsa-project.org/main/index.php/FramesPeriods). This means that by default with alsasrc/sink, we get a latency of 200ms in the src and in the sink. I am wondering if Alsa buffer size should not be set according to the audio ring buffer size but base on the period size, e.g. 2 times the period size as described in the link above. This will avoid to create latency in Alsa and keep a good size for the audio ring buffer of gstaudiobasesink so it can play its role.
Comment 4 Paul HENRYS 2013-05-12 17:27:42 UTC
Created attachment 243933 [details] [review]
Patch
Comment 5 Paul HENRYS 2013-05-13 12:40:35 UTC
Forget my last comment about the ringbuffer, alsasink latency should be set to something small if low latency is required as explained for the buffer-time property when using gst-inspect:

buffer-time: Size of audio buffer in microseconds, this is the minimum latency that the sink reports
Comment 6 Paul HENRYS 2013-05-28 06:43:30 UTC
Some updates on this bug, which is not one ;)

Actually, this patch should not be applied as it's really specific to the environment I working on. Nevertheless, comments might be useful so that will leave a trace if somebody needs one day.
This is really specific as it depends on the driver itself and limiting to a power of 2 period-size and buffer-size will not be relevant for most of the driver I guess. After, using the last patch I also had to modify some davinci-pcm file so that the ratio between buffer-size and period-size is not too high. This is defined by periods_min and was set to 16, which means that to achieve a low latency on the sink, it will require lot of interrupts and a higher load. This value is typically set to 2 in most of the sound drivers and doing so in my case and recompiling the kernel worked fine. One guy asked why it's so high without success (http://davinci-linux-open-source.1494791.n2.nabble.com/davinci-pcm-c-snd-pcm-hardware-periods-min-value-td7580155.html).
Finally the soultion was in my case (embedded device with an ARMv7 processor):
Comment 7 Paul HENRYS 2013-05-28 06:45:31 UTC
To finish my last sentence :s

Finally the soultion was in my case (embedded device with an ARMv7 processor):
  - power of 2 for buffer-size, period-size
  - reduce periods_min to 2 in the driver used
  - update threads scheduling to have higher priority for GStreamer's threads
Comment 8 Sebastian Dröge (slomo) 2013-05-28 08:09:51 UTC
That sounds like something that the driver should do IMHO, when alsasink requests the nearest period_size/buffer_size to some value.