From 53cc9d0003023c7cb670e94ce27c984e3a4865ce Mon Sep 17 00:00:00 2001
From: Peter Jankuliak
Date: Mon, 12 Aug 2024 14:53:50 +0200
Subject: [PATCH] StateMonitor: Remove `on_change` from Mutex
Improves syncing speed by about 10-15% on Android
---
state_monitor/src/lib.rs | 48 ++++++++++++++--------------------------
1 file changed, 17 insertions(+), 31 deletions(-)
diff --git a/state_monitor/src/lib.rs b/state_monitor/src/lib.rs
index ccafc8038..bf646e8fe 100644
--- a/state_monitor/src/lib.rs
+++ b/state_monitor/src/lib.rs
@@ -112,13 +112,12 @@ struct StateMonitorShared {
id: MonitorId,
parent: Option,
inner: BlockingMutex,
+ on_change: watch::Sender<()>,
}
struct StateMonitorInner {
values: IndexMap,
children: IndexMap,
- // TODO: Why is this in mutex?
- on_change: watch::Sender<()>,
}
struct ChildEntry {
@@ -175,8 +174,8 @@ impl StateMonitor {
inner: BlockingMutex::new(StateMonitorInner {
values: Default::default(),
children: Default::default(),
- on_change: watch::channel(()).0,
}),
+ on_change: watch::channel(()).0,
});
e.insert(ChildEntry {
@@ -201,7 +200,7 @@ impl StateMonitor {
// of this function because given that `self` exists it must be that `refcount` doesn't
// drop to zero anywhere in this function (and thus won't be removed from parent).
self.shared.increment_refcount();
- self.shared.changed(self.shared.lock_inner());
+ self.shared.changed();
}
Self { shared: child }
@@ -249,7 +248,9 @@ impl StateMonitor {
}
};
- self.shared.changed(lock);
+ drop(lock); // Drop ASAP
+
+ self.shared.changed();
MonitoredValue {
name,
@@ -316,7 +317,7 @@ impl Drop for StateMonitor {
}
entry.remove();
- parent.shared.changed(parent_inner);
+ parent.shared.changed();
}
}
@@ -337,8 +338,8 @@ impl StateMonitorShared {
inner: BlockingMutex::new(StateMonitorInner {
values: Default::default(),
children: Default::default(),
- on_change: watch::channel(()).0,
}),
+ on_change: watch::channel(()).0,
})
}
@@ -361,19 +362,11 @@ impl StateMonitorShared {
}
fn subscribe(self: &Arc) -> watch::Receiver<()> {
- self.lock_inner().on_change.subscribe()
+ self.on_change.subscribe()
}
- // TODO: Does this need the lock?
- fn changed(&self, lock: BlockingMutexGuard<'_, StateMonitorInner>) {
- lock.on_change.send(()).unwrap_or(());
-
- // Let's not lock self and parent at the same time to avoid potential deadlocks.
- drop(lock);
-
- if let Some(parent) = &self.parent {
- parent.shared.changed(parent.shared.lock_inner());
- }
+ fn changed(&self) {
+ self.on_change.send(()).unwrap_or(());
}
fn lock_inner(&self) -> BlockingMutexGuard<'_, StateMonitorInner> {
@@ -433,40 +426,33 @@ impl MonitoredValue {
pub fn get(&self) -> MutexGuardWrap<'_, T> {
MutexGuardWrap {
monitor: self.monitor.clone(),
- guard: Some(self.value.lock().unwrap()),
+ guard: self.value.lock().unwrap(),
}
}
}
pub struct MutexGuardWrap<'a, T> {
monitor: StateMonitor,
- // This is only None in the destructor.
- guard: Option>,
+ guard: BlockingMutexGuard<'a, T>,
}
impl<'a, T> core::ops::Deref for MutexGuardWrap<'a, T> {
type Target = T;
fn deref(&self) -> &T {
- self.guard.as_ref().unwrap()
+ &*self.guard
}
}
impl<'a, T> core::ops::DerefMut for MutexGuardWrap<'a, T> {
fn deref_mut(&mut self) -> &mut T {
- &mut *(self.guard.as_mut().unwrap())
+ &mut *self.guard
}
}
impl<'a, T> Drop for MutexGuardWrap<'a, T> {
fn drop(&mut self) {
- {
- // Unlock this before we try to lock the parent monitor.
- self.guard.take();
- }
- self.monitor
- .shared
- .changed(self.monitor.shared.lock_inner());
+ self.monitor.shared.changed();
}
}
@@ -481,7 +467,7 @@ impl Drop for MonitoredValue {
v.refcount -= 1;
if v.refcount == 0 {
e.remove();
- self.monitor.shared.changed(lock);
+ self.monitor.shared.changed();
}
}
Entry::Vacant(_) => unreachable!(),