Skip to content

Commit 34fda75

Browse files
committed
Add size-based optimization to MonitorUpdatingPersister
Introduces an optimization to the MonitorUpdatingPersister to avoid writing differential updates for small channel monitors. When a channel monitor is smaller than a configurable threshold , the persister will now write the full monitor instead of an update. This avoids the I/O overhead of creating and managing many small update files for monitors that don't benefit significantly from differential updates.
1 parent 8aae34e commit 34fda75

File tree

1 file changed

+46
-2
lines changed

1 file changed

+46
-2
lines changed

lightning/src/util/persist.rs

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,13 @@ where
446446
/// If you have many stale updates stored (such as after a crash with pending lazy deletes), and
447447
/// would like to get rid of them, consider using the
448448
/// [`MonitorUpdatingPersister::cleanup_stale_updates`] function.
449+
///
450+
/// # Size-based persistence optimization
451+
///
452+
/// For small channel monitors (below `min_monitor_size_for_updates_bytes` bytes when serialized),
453+
/// this persister will always write the full monitor instead of individual updates. This avoids
454+
/// the overhead of managing update files and later compaction for tiny monitors that don't benefit
455+
/// from differential updates.
449456
pub struct MonitorUpdatingPersister<K: Deref, L: Deref, ES: Deref, SP: Deref, BI: Deref, FE: Deref>
450457
where
451458
K::Target: KVStore,
@@ -458,6 +465,7 @@ where
458465
kv_store: K,
459466
logger: L,
460467
maximum_pending_updates: u64,
468+
min_monitor_size_for_updates_bytes: usize,
461469
entropy_source: ES,
462470
signer_provider: SP,
463471
broadcaster: BI,
@@ -475,7 +483,7 @@ where
475483
BI::Target: BroadcasterInterface,
476484
FE::Target: FeeEstimator,
477485
{
478-
/// Constructs a new [`MonitorUpdatingPersister`].
486+
/// Constructs a new [`MonitorUpdatingPersister`] with a default minimum monitor size threshold.
479487
///
480488
/// The `maximum_pending_updates` parameter controls how many updates may be stored before a
481489
/// [`MonitorUpdatingPersister`] consolidates updates by writing a full monitor. Note that
@@ -491,14 +499,45 @@ where
491499
/// less frequent "waves."
492500
/// - [`MonitorUpdatingPersister`] will potentially have more listing to do if you need to run
493501
/// [`MonitorUpdatingPersister::cleanup_stale_updates`].
502+
///
503+
/// This sets `min_monitor_size_for_updates_bytes` to 4096 bytes (4 KiB), which is a reasonable
504+
/// default for most use cases. Monitors smaller than this will be persisted in full rather than
505+
/// using update-based persistence. Use [`MonitorUpdatingPersister::new_with_monitor_size_threshold`]
506+
/// if you need a custom threshold.
494507
pub fn new(
495508
kv_store: K, logger: L, maximum_pending_updates: u64, entropy_source: ES,
496509
signer_provider: SP, broadcaster: BI, fee_estimator: FE,
510+
) -> Self {
511+
Self::new_with_monitor_size_threshold(
512+
kv_store,
513+
logger,
514+
maximum_pending_updates,
515+
4096,
516+
entropy_source,
517+
signer_provider,
518+
broadcaster,
519+
fee_estimator,
520+
)
521+
}
522+
523+
/// Constructs a new [`MonitorUpdatingPersister`] with a custom minimum monitor size threshold.
524+
///
525+
/// The `min_monitor_size_for_updates_bytes` parameter sets the minimum serialized size (in bytes)
526+
/// for a [`ChannelMonitor`] to use update-based persistence. Monitors smaller than this threshold
527+
/// will always be persisted in full, avoiding the overhead of managing update files for tiny
528+
/// monitors. Set to 0 to always use update-based persistence regardless of size.
529+
///
530+
/// For other parameters, see [`MonitorUpdatingPersister::new`].
531+
pub fn new_with_monitor_size_threshold(
532+
kv_store: K, logger: L, maximum_pending_updates: u64,
533+
min_monitor_size_for_updates_bytes: usize, entropy_source: ES, signer_provider: SP,
534+
broadcaster: BI, fee_estimator: FE,
497535
) -> Self {
498536
MonitorUpdatingPersister {
499537
kv_store,
500538
logger,
501539
maximum_pending_updates,
540+
min_monitor_size_for_updates_bytes,
502541
entropy_source,
503542
signer_provider,
504543
broadcaster,
@@ -752,7 +791,12 @@ where
752791
) -> chain::ChannelMonitorUpdateStatus {
753792
const LEGACY_CLOSED_CHANNEL_UPDATE_ID: u64 = u64::MAX;
754793
if let Some(update) = update {
755-
let persist_update = update.update_id != LEGACY_CLOSED_CHANNEL_UPDATE_ID
794+
// Check if monitor is too small for update-based persistence
795+
let monitor_size = monitor.serialized_length();
796+
let use_full_persistence = monitor_size < self.min_monitor_size_for_updates_bytes;
797+
798+
let persist_update = !use_full_persistence
799+
&& update.update_id != LEGACY_CLOSED_CHANNEL_UPDATE_ID
756800
&& update.update_id % self.maximum_pending_updates != 0;
757801
if persist_update {
758802
let monitor_key = monitor_name.to_string();

0 commit comments

Comments
 (0)