From 6da93b8306df3c3345e63a4f2e36d923e3360580 Mon Sep 17 00:00:00 2001 From: Sebastian Reinhard Date: Mon, 18 Sep 2023 11:05:52 +0200 Subject: [PATCH] file_storage: Wrap `File` in `BufWriter` When exiting my application, it would freeze for around a minute waiting to finish writing ca. 40MB to file storage. Some quick profiling revealed that it was spending all that time in `File::write`, presumably making a large number of system calls writing tiny amounts of data at a time. We can avoid this by buffering writes using a `BufWriter`, just like we already do with `BufReader`. With this change, my application takes around 1-2 seconds to exit, with the majority of that time spent serializing `ron`. I'm sure there are further potential performance improvements there, but this is already an order of magnitude or two better. I also fixed the call to `log::warn!`, which was using incorrect formatting syntax and not including the error message. --- crates/eframe/src/native/file_storage.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/crates/eframe/src/native/file_storage.rs b/crates/eframe/src/native/file_storage.rs index 1b4c254c2c2..6b059e81799 100644 --- a/crates/eframe/src/native/file_storage.rs +++ b/crates/eframe/src/native/file_storage.rs @@ -1,5 +1,6 @@ use std::{ collections::HashMap, + io::Write, path::{Path, PathBuf}, }; @@ -126,10 +127,13 @@ fn save_to_disk(file_path: &PathBuf, kv: &HashMap) { match std::fs::File::create(file_path) { Ok(file) => { + let mut writer = std::io::BufWriter::new(file); let config = Default::default(); - if let Err(err) = ron::ser::to_writer_pretty(file, &kv, config) { - log::warn!("Failed to serialize app state: {err}"); + if let Err(err) = ron::ser::to_writer_pretty(&mut writer, &kv, config) + .and_then(|_| writer.flush().map_err(|err| err.into())) + { + log::warn!("Failed to serialize app state: {}", err); } else { log::trace!("Persisted to {:?}", file_path); }