mirror of
https://github.com/storytold/effectcraft.git
synced 2026-10-29 20:47:18 -06:00
Disk cache: apply the free-space reading where it's taken, evict off the UI thread at open (#2551)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
74ea0be88f
commit
8ab492d8cd
@@ -84,11 +84,7 @@ impl Session {
|
||||
/// re-apply the cache budgets when the reading changes them. Returns the effective budgets.
|
||||
/// The disk cache's free disk space is read the same way (it keeps a reserve free).
|
||||
pub fn memory_tick(&mut self) -> crate::prefs::CacheBudgets {
|
||||
if let Some(dc) = &self.disk_cache {
|
||||
dc.set_disk_space(self.disk_watch.latest());
|
||||
let folder = dc.folder().to_path_buf();
|
||||
self.disk_watch.poll_with("ec-disk-space", move || crate::sysinfo::disk_space(&folder));
|
||||
}
|
||||
self.poll_disk_space();
|
||||
let before = self.prefs.cache_budgets(self.sys_memory);
|
||||
self.sys_memory = self.memory_watch.latest().or(self.sys_memory);
|
||||
self.memory_watch.poll();
|
||||
@@ -104,6 +100,19 @@ impl Session {
|
||||
after
|
||||
}
|
||||
|
||||
/// Read the disk cache's free disk space in the background and apply it there (the reserve
|
||||
/// it keeps free): the free space and the cache's size are taken at the same moment, and the
|
||||
/// reader holds its own cache, so a reading never reaches another folder's.
|
||||
fn poll_disk_space(&mut self) {
|
||||
if let Some(dc) = &self.disk_cache {
|
||||
let dc = dc.clone();
|
||||
self.disk_watch.poll_with("ec-disk-space", move || {
|
||||
dc.set_disk_space(crate::sysinfo::disk_space(dc.folder()));
|
||||
Some(())
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// Apply Settings ▸ Media & Disk Cache ▸ Disk Cache: open (or close) the persistent cache
|
||||
/// and attach it to the layer cache. Without a folder setting the platform cache folder is
|
||||
/// used, but only by frontends with a settings store (headless sessions stay off disk).
|
||||
@@ -150,6 +159,8 @@ impl Session {
|
||||
},
|
||||
};
|
||||
self.disk_cache = Some(dc.clone());
|
||||
// The reserve applies from the start (a new folder's watcher is idle).
|
||||
self.poll_disk_space();
|
||||
let salt = self.refresh_disk_salt(true).unwrap_or_default();
|
||||
self.layer_cache.set_disk(Some((dc.clone(), salt)));
|
||||
// Roto Brush / Object Matte segmentations persist there too (held weakly: switching the
|
||||
|
||||
@@ -44,8 +44,9 @@ impl<T> Default for Watch<T> {
|
||||
|
||||
/// The system's memory ([`memory`]).
|
||||
pub type MemoryWatch = Watch<SysMemory>;
|
||||
/// The disk cache's disk: `(total, available)` bytes ([`disk_space`]).
|
||||
pub type DiskWatch = Watch<(u64, u64)>;
|
||||
/// The disk cache's free-space reading ([`disk_space`]): the reader applies it to its cache
|
||||
/// itself, so only the busy guard is used.
|
||||
pub type DiskWatch = Watch<()>;
|
||||
|
||||
impl<T: Copy + Send + 'static> Watch<T> {
|
||||
/// Start a new reading in the background on a thread called `name` (no threads on the web:
|
||||
|
||||
@@ -320,10 +320,12 @@ impl DiskCache {
|
||||
dropped: AtomicU64::new(0),
|
||||
failed: AtomicU64::new(0),
|
||||
tmp_counter: AtomicU64::new(0),
|
||||
queue: Arc::new((Mutex::new(Queue { jobs: Default::default(), busy: false }), Condvar::new())),
|
||||
queue: Arc::new((Mutex::new(Queue { jobs: Default::default(), busy: cfg!(not(target_arch = "wasm32")) }), Condvar::new())),
|
||||
min_layer_ms: AtomicU64::new(30),
|
||||
});
|
||||
dc.rescan();
|
||||
// Shrinking a large cache deletes many files: the writer thread does it.
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
dc.evict();
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
{
|
||||
@@ -644,6 +646,15 @@ impl DiskCache {
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
fn writer(dc: std::sync::Weak<DiskCache>, q: Arc<(Mutex<Queue>, Condvar)>) {
|
||||
let (m, cv) = &*q;
|
||||
// The eviction at open (a lower limit than the folder holds), off the opening thread;
|
||||
// `busy` starts set, so `flush` waits for it.
|
||||
if let Some(cache) = dc.upgrade() {
|
||||
cache.evict();
|
||||
}
|
||||
if let Ok(mut g) = m.lock() {
|
||||
g.busy = false;
|
||||
}
|
||||
cv.notify_all();
|
||||
loop {
|
||||
let job = {
|
||||
let Ok(mut g) = m.lock() else { return };
|
||||
|
||||
Reference in New Issue
Block a user