RustAudio / cpal

Cross-platform audio I/O library in pure Rust
Apache License 2.0
2.74k stars 364 forks source link

Slow enumeration of output devices on Windows #867

Open adrian17 opened 8 months ago

adrian17 commented 8 months ago

Demo code:

use cpal::traits::{HostTrait, DeviceTrait};
fn main() {
    let audio_host = cpal::default_host();
    let mut t = std::time::Instant::now();
    if let Ok(devices) = audio_host.output_devices() {
        for device in devices {
            println!("{:?} {:?}", t.elapsed(), device.name());
            t = std::time::Instant::now();
        }
    }
}

Takes surprisingly slow on my machine:

108.0278ms Ok("Realtek Digital Output (Realtek(R) Audio)")
99.4321ms Ok("Realtek HD Audio 2nd output (Realtek(R) Audio)")

We query the output devices just before displaying them, which can cause a noticeable lag if there are more devices. A similar query on my linux VM takes <10ms per device.

j-n-f commented 5 months ago

Same here.

If I time from when I start interacting with cpal I can fetch the Host in less than 1ms.

It takes about 133ms from start to fetch the list of devices (host.output_devices()).

When I go to select a specific device by name and finally get it it's about 825ms from start.

I can't see anything that I could cache to try and speed things up (and then fall back on a complete scan if the usual device isn't found).

In my case < 1s is still pretty good, but what concerns me is that the lookup time scales with the number of devices (I have 3 on this host when using ASIO). @adrian17 sees about 100ms per device (guessing this is with the WASAPI driver), I'm seeing a little over 200ms with ASIO.

jesnor commented 1 month ago

I think the problem is that when asking for input or output devices (but not when calling just host.devices()) it enumerates all formats that the devices support to check if it's an input or output device. This should be a quite simple optimization.