Optimize AudioPlayer::play by offloading sync file I/O to spawn_blocking (#29)

* perf(audio_player): offload synchronous I/O and decoder init to spawn_blocking

Moved synchronous file system operations (`fs::File::open` and `file_path.exists()`) and CPU-bound decoder initialization (`Decoder::try_from`) inside the async `AudioPlayer::play` method to `tokio::task::spawn_blocking`.
This prevents starving the Tokio worker threads during disk operations and significantly reduces event loop latency.

Co-authored-by: arabianq <55220741+arabianq@users.noreply.github.com>

* perf(audio_player): offload synchronous I/O and decoder init to spawn_blocking

Moved synchronous file system operations (`fs::File::open` and `file_path.exists()`) and CPU-bound decoder initialization (`Decoder::try_from`) inside the async `AudioPlayer::play` method to `tokio::task::spawn_blocking`.
This prevents starving the Tokio worker threads during disk operations and significantly reduces event loop latency.

Co-authored-by: arabianq <55220741+arabianq@users.noreply.github.com>

---------

Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
This commit is contained in:
Tarasov Aleksandr
2026-03-08 00:41:34 +03:00
committed by GitHub
parent d6effc972e
commit 95761f6a5a
2 changed files with 127 additions and 6 deletions
+14 -6
View File
@@ -278,12 +278,20 @@ impl AudioPlayer {
file_path: &Path,
concurrent: bool,
) -> Result<u32, Box<dyn Error>> {
if !file_path.exists() {
return Err(format!("File does not exist: {}", file_path.display()).into());
}
let path_buf = file_path.to_path_buf();
let file = fs::File::open(file_path)?;
match Decoder::try_from(file) {
let decoder_result = tokio::task::spawn_blocking(move || -> Result<_, Box<dyn Error + Send + Sync>> {
if !path_buf.exists() {
return Err(format!("File does not exist: {}", path_buf.display()).into());
}
let file = fs::File::open(&path_buf)?;
let decoder = Decoder::try_from(file).map_err(|e| Box::new(e) as Box<dyn Error + Send + Sync>)?;
Ok(decoder)
})
.await?;
match decoder_result {
Ok(source) => {
if !concurrent {
self.tracks.clear();
@@ -312,7 +320,7 @@ impl AudioPlayer {
Ok(id)
}
Err(err) => Err(err.into()),
Err(err) => Err(err as Box<dyn Error>),
}
}