-
Notifications
You must be signed in to change notification settings - Fork 51
Refactor: use atomics for tracker stats #1138
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Refactor: use atomics for tracker stats #1138
Conversation
instead of RwLock. Atomics are lock-free. This eliminates the overhead of locks and reduces contention.
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## develop #1138 +/- ##
===========================================
+ Coverage 76.21% 76.24% +0.03%
===========================================
Files 173 173
Lines 11543 11560 +17
Branches 11543 11560 +17
===========================================
+ Hits 8797 8814 +17
Misses 2584 2584
Partials 162 162 ☔ View full report in Codecov by Sentry. |
|
It seems the performance has not changed too much. Best case, from 357088 to 347733 (−2.6%) However the I guess I could use Relaxed Ordering, too. That should be better and viable in this case. I will try with Relaxed Ordering just to see if it makes a difference. This PRBest case Worst case
|
|
It seems the performance has not changed too much with Relaxed Ordering either. Best case, from 357088 to 340008 (−4.7%) Best caseWorst case |
|
ACk c6c6331 |
|
Hi @da2ce7 I think the problem is we use the channel. In torrust-actix, stats are a direct attribute of the We are using a channel sending stats events to the event handler thread: pub struct Keeper {
pub repository: Repository,
}
impl Keeper {
#[must_use]
pub fn new() -> Self {
Self {
repository: Repository::new(),
}
}
#[must_use]
pub fn new_active_instance() -> (Box<dyn Sender>, Repository) {
let mut stats_tracker = Self::new();
let stats_event_sender = stats_tracker.run_event_listener();
(stats_event_sender, stats_tracker.repository)
}
pub fn run_event_listener(&mut self) -> Box<dyn Sender> {
let (sender, receiver) = mpsc::channel::<Event>(CHANNEL_BUFFER_SIZE);
let stats_repository = self.repository.clone();
tokio::spawn(async move { dispatch_events(receiver, stats_repository).await });
Box::new(ChannelSender { sender })
}
}Therefore, stats updates are anyway sequential. I will keep the current state because I think decoupling stats from the tracker with events makes the tracker code simpler and easier to test. I think it's also easier to refactor metrics while sending the same events. I think events will always be the same even if we reorganise them, but metrics can change a lot. |
Use atomics for tracker stats instead of RwLock. Atomics are lock-free. This eliminates the overhead of locks and reduces contention.
Subtasks
RwLockfor Metrics with individualAtomicU64for each metric.