qubes-issues icon indicating copy to clipboard operation
qubes-issues copied to clipboard

Audio stuttering with audiovm

Open 3hhh opened this issue 5 months ago • 8 comments

How to file a helpful issue

Qubes OS release

4.2

Brief summary

After starting to use sys-audio my audio playback started to stutter and cut off - especially under dom0 load.

Steps to reproduce

  1. Install sys-audio as per this guide.
  2. Put dom0 under load.

Expected behavior

Audio works reliably.

Actual behavior

Audio stutters.

Additional information

A lot of these errors can be found in ~/.xsession-errors:

1752763915.753912 Stream underrun.
1752763915.759997 Stream started.

The sound card is connected via USB.

Possibly related: #9986

3hhh avatar Jul 17 '25 14:07 3hhh

Hm, looks like the Intel PCIE card has less issues than the USB sound card, i.e. it might be something related to USB autosuspend or so.

I also noticed a lot of other weird messages in ~/.xsession-errors. Apparently the audiovm believes that it should also do some GUI stuff for other VMs? I don't remember to have configured that.

Failed to read /guivm-windows-prefix
...
1752784369.840227 Cork requested and playback vchan empty. Draining playback stream.
1752784369.844476 Stream uncork
app: Connection to qubesd terminated, reconnecting in 1.0 seconds
app: Failed to handle event: None, connection-established, {}
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/qubesadmin/base.py", line 232, in __getattr__
    property_str = self.qubesd_call(
                   ^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/qubesadmin/base.py", line 76, in qubesd_call
    return self.app.qubesd_call(dest, method, arg, payload,
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/qubesadmin/app.py", line 912, in qubesd_call
    raise qubesadmin.exc.QubesDaemonAccessError(
qubesadmin.exc.QubesDaemonAccessError: Service call error: Request refused


During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/qubesadmin/events/__init__.py", line 259, in handle
    handler(subject, event, **kwargs)
  File "/usr/lib/python3/dist-packages/qubesadmin/tools/qvm_start_daemon.py", line 696, in on_connection_established
    for vm in self.app.domains:
  File "/usr/lib/python3/dist-packages/qubesadmin/app.py", line 151, in __iter__
    self.refresh_cache()
  File "/usr/lib/python3/dist-packages/qubesadmin/app.py", line 96, in refresh_cache
    elif vm.klass != self._vm_list[vm.name]['class']:
         ^^^^^^^^
  File "/usr/lib/python3/dist-packages/qubesadmin/base.py", line 239, in __getattr__
    raise qubesadmin.exc.QubesPropertyAccessError(item)
qubesadmin.exc.QubesPropertyAccessError: Failed to access 'klass' property
2025-07-17 22:34:36.232 qrexec-fork-server[1828]: qrexec-agent-data.c:256:handle_new_process_common: executed: QUBESRPC qubes.SetMonitorLayout dom0 (pid 1830)
2025-07-17 22:34:37.905 qrexec-fork-server[1828]: qrexec-agent-data.c:288:handle_new_process_common: pid 1830 exited with 0
disp1019: Failed to start GUI for disp1019: Service call error: Request refused

3hhh avatar Jul 17 '25 20:07 3hhh

Does doing sudo xl sched-credit -d sys-audio -w 2048 help?

Atrate avatar Jul 18 '25 10:07 Atrate

Ok, I think I managed to mostly fix it by

  1. selecting a different audio profile for my sound card in the pavucontrol configuration ("Pro Audio" was apparently too resource hungry).
  2. setting the preempt=full threadirqs kernel options for the audiovm (I happen to use the debian-12-minimal in-VM kernel). This is a very common recommendation for Linux audio. I also use it in dom0. The sound card irq inside sys-audio appears to use a constant ~8% CPU with a single source.

Making Xen schedule sys-audio more often as indicated by @Atrate might also help, but I haven't tested that.

I'll leave this bug open to possibly change the defaults in Qubes OS (e.g. set 2. by default) or at least document these possible issues as e.g. part of #8093.

3hhh avatar Jul 18 '25 16:07 3hhh

@3hhh so, what would you suggest adding to kernel parameters in case of default dom0 audio solution to improve sound performance? I have sound issues from Windows qube (#10320), maybe it would help.

jamke avatar Oct 26 '25 05:10 jamke

On 10/26/25 06:14, jamke wrote:

jamke left a comment (QubesOS/qubes-issues#10063)

@3hhh so, what would you suggest adding to kernel parameters in case of default dom0 audio solution to improve sound performance? I have sound issues from Windows qube (#10320), maybe it would help.

I use preempt=full threadirqs in dom0 and all VMs. Actually I don't see much of an issue with these kernel parameters on end user systems as they cause latency for interrupts to be optimized. Setting these options won't be a good idea on servers where workloads are a priority.

For my real-time audio machines I also use a real-time kernel, set cpufreq.default_governor=performance and disable all CPU bug mitigations for maximum performance, but I certainly don't recommend the latter for Qubes OS for obvious security reasons.

3hhh avatar Oct 26 '25 17:10 3hhh

I use preempt=full threadirqs in dom0 and all VMs. Actually I don't see much of an issue with these kernel parameters on end user systems as they cause latency for interrupts to be optimized. Setting these options won't be a good idea on servers where workloads are a priority.

How did you configure this for your VMs? I presume adding it to /etc/default/grub in dom0 is enough, but what about VMs that use the same kernel as dom0? Will it be inherited?

Atrate avatar Oct 26 '25 19:10 Atrate

On 10/26/25 20:00, Atrate wrote:

Atrate left a comment (QubesOS/qubes-issues#10063)

I use preempt=full threadirqs in dom0 and all VMs. Actually I don't see much of an issue with these kernel parameters on end user systems as they cause latency for interrupts to be optimized. Setting these options won't be a good idea on servers where workloads are a priority.

How did you configure this for your VMs? I presume adding it to /etc/default/grub in dom0 is enough, but what about VMs that use the same kernel as dom0? Will it be inherited?

For in-VM kernels you can use the same method as in dom0 inside their template VM. For kernels provided by dom0 (Qubes OS default) you can use qvm-prefs [vm] kernelopts. This may be inherited from templates to application VMs - I'm not 100% sure.

3hhh avatar Oct 28 '25 16:10 3hhh

I'm on Qubes 4.3 and using essentialy only debian-13-xfce VMs with pipewire.

I just tried a combo of: dom0:~$ qvm-prefs sys-audio kernelopts "preempt=full threadirqs"

$ sudo xl sched-credit2 -d sys-audio -w 4096

After restarting my sys-audio vm and connecting to my bluetooth headset, I still have pretty bad sound.

Since it works without shuttering again after restarting sys-audio+my app vm, I kee notes for next time:

  • Running simple speaker-test -t sin from my audio-vm works without stuttering
  • Running the same from my appvm will cause stuttering (I guess it's related to too short buffering)

Next time I have this issue, I will try to change the qubes pipewire settings in my audio-vm:

$ cat /usr/share/pipewire/pipewire.conf.d/30_qubes.conf
context.properties = {
   # Uncomment this if the default quantum is too small and you are
   # experiencing a bunch of overruns or underruns.
   #default.clock.min-quantum = 512

   # Set the allowed audio rates to work around problems with Firefox
   default.clock.allowed-rates = [ 44100 48000 ]

   # Default size of the recording buffer in bytes.  This is very large
   # because a larger buffer only wastes some memory, whereas a small
   # buffer risks overruns in the audio daemon (pacat-simple-vchan).
   org.qubes-os.record.buffer-size = 1048576

   # Default size of the playback buffer in bytes.  This is smaller
   # because a large buffer provides less benefit here: it is much more
   # likely for the audio daemon to underrun (not be able to obtain
   # enough samples) than for this module to overrun (run out of space).
   org.qubes-os.playback.buffer-size = 65536

Maybe increasing playback.buffer-size ?

It can be quickly tested as I just need to restart pipewire: systemctl restart pipewire --user

ptitdoc avatar Dec 03 '25 11:12 ptitdoc