Weblog entry #90 for dkg

libasound2-plugins is a resource hog!
Posted by dkg on Fri 21 Dec 2012 at 01:50
Tags: , , ,
I run mpd on debian on "igor", an NSLU2 -- a very low-power ~266MHz armel machine, with no FPU and a scanty 32MiB of RAM. This serves nicely to feed my stereo with music that is controllable from anywhere on my LAN. When playing music and talking to a single mpd client, the machine is about 50% idle.

However, during a recent upgrade, something wanted to pull in pulseaudio, which in turn wanted to pull in libasound2-plugins, and i distractedly (foolishly) let it. With that package installed, after an mpd restart, the CPU was completely thrashed (100% utilization) and music only played in stutters of 1 second interrupted by a couple seconds of silence. igor was unusable for its intended purpose.

Getting rid of pulseaudio was my first attempt to fix the stuttering, but the problem remained even after pulse was all gone and mpd was restarted.

Then i did a little search of which packages had been freshly installed in the recent run:

grep ' install .* <none> ' /var/log/dpkg.log
and used that to pick out the offending package.

After purging libasound2-plugins and restarting mpd, the igor is back in action.

Lesson learned: on low-overhead machines, don't allow apt to install recommends!

echo 'APT::Install-Recommends "0";' >> /etc/apt/apt.conf
And it should go without saying, but sometimes i get sloppy: i need to pay closer attention during an "apt-get dist-upgrade"

 

Comments on this Entry

Posted by Anonymous (94.198.xx.xx) on Fri 21 Dec 2012 at 09:16
No, you got that wrong. It must be:

On Debian, don’t allow APT to install Recommends.

Period.

[ Parent | Reply to this comment ]

Posted by dkg (2001:0xx:0xx:0xxx:0xxx:0xxx:xx) on Fri 21 Dec 2012 at 09:28
[ View dkg's Scratchpad | View Weblogs ]
Actually, on desktop machines, i find i almost always do want apt to install recommends.

low-power machines and servers i tend to be more conservative with, but installing recommends by default is pretty handy when i want to try out the full expected capabilities of a piece of software i've just installed..

[ Parent | Reply to this comment ]

Posted by dkg (2001:0xx:0xx:0xxx:0xxx:0xxx:xx) on Fri 21 Dec 2012 at 18:01
[ View dkg's Scratchpad | View Weblogs ]
I just received this nice in-depth followup from Alexander E. Patrakov via e-mail (i haven't had a chance yet to do the tests he describes, but i will post my results here when i do):
Well, I think that it would be more appropriate to find the underlying performance issue (bug?) and tune the relevant tunables than to say that libasound2-plugins is a resource hog.

The thing that eats CPU is a resampler. The default resampler in ALSA is a simple low-quality linear-interpolation one, and libasound2-plugins provide two plugins relevant for us: (a) a better-quality resampler that uses more CPU, (b) pulseaudio plugin that only copies existing samples. Pulseaudio, in turn, contains a resampler.

Let's assume that you typically listen to FLACs and MP3s that have the 44100 Hz sample rate.

So, let's first consider a typical PulseAudio setup. An ALSA app tries to output sound. The default output device is pulseaudio, and its ALSA plugin accepts all sample rates. So, no sample rate conversion is necessary at this level, and thus a resampler is not invoked. PulseAudio also defaults to 44100 Hz sample rate if the hardware supports it. I assume that your hardware doesn't support that rate (you can check with this command while a song is being played through pulseaudio: cat /proc/asound/card0/pcm0p/sub0/hw_params), that's why you need resampling. If your card does support 44100 Hz and PulseAudio eats CPU even though it doesn't need to resample, I'd call it a bug that needs reporting.

Pulseaudio's tunable for resampling is located in /etc/pulse/daemon.conf and is called, unsurprisingly, "resample-method". The default is "speex-float-3", and that's definitely not appropriate for an ARM device. You can have better luck with "speex-fixed-0" or even maybe "speex-fixed-3" (same quality as the default "speex-float-3", but implemented in fixed point).

Now let's consider a typical ALSA-only setup. The default device now uses "plug" and "dmix" plugins before sending audio samples to the hardware. Plug converts the sample rate if necessary. Dmix mixes. Dmix accepts only one sample rate, 48000 Hz by default. This can be tuned by adding a line similar to the following to /etc/asound.conf:

defaults.pcm.dmix.rate 44100

Of course, this will not work if the card doesn't actually support 44100 Hz. Then, the quality of the resampler can, theoretically, be tuned by setting this parameter:

defaults.pcm.rate_converter "speexrate"

The default is "speexrate", and the available values (except "linear" which is built-in) can be obtained by running this command:

ls /usr/lib*/alsa-lib/libasound_module_rate_*.so

(as what comes in place of the "*"). Unfortunately, there is no lower-quality version of speexrate, lavcrate is unreliable, and anything based on libsamplerate uses floating-point instructions. To add insult to the injury, in some Debian releases AFAIK speex was miscompiled to prefer floating-point on ARM. So in practice, yes, the best ALSA-only solution would be to use the linear resampler wither by explicitly configuring it, or by uninstalling libasound2-plugins.

Still, I would like you to give pulseaudio one more try. Uninstall it only if you can't make it work, or can't tell the difference between the working resamplers by ear (you need music that contains some relatively long trumpet, violin or female-voice solo notes in order to tell the difference).

[ Parent | Reply to this comment ]

Posted by dkg (2001:0xx:0xx:0xxx:0xxx:0xxx:xx) on Fri 28 Dec 2012 at 03:06
[ View dkg's Scratchpad | View Weblogs ]
I think the USB audio device ("0c45:167f Microdia") attached to igor only does 48000Hz:
0 igor:~# cat /proc/asound/card0/pcm0p/sub0/hw_params 
access: MMAP_INTERLEAVED
format: S16_LE
subformat: STD
channels: 2
rate: 48000 (48000/1)
period_size: 6000
buffer_size: 24001
0 igor:~# 
So i'm willing to try pulseaudio here, but i'm still having no luck.

After having installed pulseaudio, modified /etc/pulse/daemon.conf to include resample-method = speex-fixed-0, and updated /etc/mpd.conf to use a pulseaudio output instead of an alsa output. In this configuration, i still get some stuttering, and pulseaudio (running under the mpd user) takes up about 40% of the CPU, while the mpd process itself takes up about 35%. The stuttering is noticeably better than then pulseless libasound2-plugins situation, though!

Purging libasound2-plugins (which also purges pulseaudio), and reinstating the original alsa-targeted /etc/mpd.conf, there is no stuttering, and the mpd process itself takes up between 35% and 50% of the CPU.

I should note that due to the warning from the pulse initscript that pulse was not running in system mode, I followed a bit of a wild goose chase about setting it up in system mode, which it turns out is a bad idea. I've filed a bug about debian's quasi-encouragement of system mode. The above figures were without system mode.

So my conclusion is that pulse (even when i've tuned the resampling) isn't a good fit for a system as low-powered as the NSLU2.

[ Parent | Reply to this comment ]