From 7e246b20e9b4b1b813c5253fa7cfc227c95f40f9 Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Tue, 14 Jul 2026 10:54:33 +0000 Subject: [PATCH] fix: avoid rewriting peer list file when unchanged (#1488) save_peer_list() ran unconditionally every 60s from the discovery loop, writing the same data to disk even when the peer set hadn't changed. Compare the newly encoded peer list against the bytes already on disk and skip the write when they match. Fixes #1457 Reviewed-on: https://git.deuxfleurs.fr/Deuxfleurs/garage/pulls/1488 Reviewed-by: Alex --- src/rpc/system.rs | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/src/rpc/system.rs b/src/rpc/system.rs index 0cd301ff..246d4d86 100644 --- a/src/rpc/system.rs +++ b/src/rpc/system.rs @@ -3,7 +3,7 @@ use std::collections::{HashMap, HashSet}; use std::io::{Read, Write}; use std::net::{IpAddr, SocketAddr}; use std::path::{Path, PathBuf}; -use std::sync::{Arc, RwLock, RwLockReadGuard}; +use std::sync::{Arc, Mutex, RwLock, RwLockReadGuard}; use std::time::{Duration, Instant}; use arc_swap::ArcSwapOption; @@ -24,6 +24,7 @@ use garage_util::config::KubernetesDiscoveryConfig; use garage_util::config::{Config, DataDirEnum}; use garage_util::data::*; use garage_util::error::*; +use garage_util::migrate::Migrate; use garage_util::persister::Persister; use garage_util::time::*; @@ -89,6 +90,9 @@ pub struct System { pub id: Uuid, persist_peer_list: Persister, + // Cache of the bytes last read from / written to the peer list file, + // to avoid waking up the disk with a read on every save_peer_list() call. + cached_peer_list_bytes: Mutex>>, pub(crate) local_status: RwLock, node_status: RwLock>, @@ -311,6 +315,7 @@ impl System { let sys = Arc::new(System { id: netapp.id.into(), persist_peer_list, + cached_peer_list_bytes: Mutex::new(None), local_status: RwLock::new(local_status), node_status: RwLock::new(HashMap::new()), netapp: netapp.clone(), @@ -779,10 +784,23 @@ impl System { peer_list.extend(prev_peer_list.0); } - // Save new peer list to file - self.persist_peer_list - .save_async(&PeerList(peer_list)) - .await + // Sort for a deterministic encoding, so that we can detect below + // whether the peer list actually changed since last time. + peer_list.sort_by_key(|(id, _)| *id); + + let new_peer_list = PeerList(peer_list); + let new_peer_list_bytes = new_peer_list.encode()?; + + // Skip writing to disk if nothing changed since the last save, + // but still cache the bytes so we don't have to read the file again. + let cached_peer_list_bytes = self.cached_peer_list_bytes.lock().unwrap().clone(); + if cached_peer_list_bytes.as_deref() == Some(&new_peer_list_bytes[..]) { + return Ok(()); + } + + self.persist_peer_list.save_async(&new_peer_list).await?; + *self.cached_peer_list_bytes.lock().unwrap() = Some(new_peer_list_bytes); + Ok(()) } }