Skip to content

Commit

Permalink
enhance: remove redundant check and improve efficiency
Browse files Browse the repository at this point in the history
  • Loading branch information
ihciah committed Apr 3, 2024
1 parent 31e9a1a commit 9404c88
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 30 deletions.
22 changes: 12 additions & 10 deletions monoio/src/time/driver/wheel/level.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ use crate::time::driver::{EntryList, TimerHandle, TimerShared};
/// Wheel for a single level in the timer. This wheel contains 64 slots.
pub(crate) struct Level {
level: usize,
slot_range: u64,
level_range: u64,

/// Bit field tracking which slots currently contain entries.
///
Expand Down Expand Up @@ -56,6 +58,8 @@ impl Level {

Level {
level,
slot_range: slot_range(level),
level_range: level_range(level),
occupied: 0,
slot: [
ctor(),
Expand Down Expand Up @@ -139,12 +143,10 @@ impl Level {
// From the slot index, calculate the `Instant` at which it needs to be
// processed. This value *must* be in the future with respect to `now`.

let level_range = level_range(self.level);
let slot_range = slot_range(self.level);

// TODO: This can probably be simplified w/ power of 2 math
let level_start = now - (now % level_range);
let mut deadline = level_start + slot as u64 * slot_range;
// Compute the start date of the current level by masking the low bits
// of `now` (`level_range` is a power of 2).
let level_start = now & !(self.level_range - 1);
let mut deadline = level_start + slot as u64 * self.slot_range;

if deadline <= now {
// A timer is in a slot "prior" to the current time. This can occur
Expand All @@ -165,7 +167,7 @@ impl Level {
// therefore means we're actually looking at a slot in the future.
debug_assert_eq!(self.level, super::NUM_LEVELS - 1);

deadline += level_range;
deadline += self.level_range;
}

debug_assert!(
Expand All @@ -175,8 +177,8 @@ impl Level {
deadline,
now,
self.level,
level_range,
slot_range,
self.level_range,
self.slot_range,
slot,
self.occupied
);
Expand All @@ -194,7 +196,7 @@ impl Level {
}

// Get the slot for now using Maths
let now_slot = (now / slot_range(self.level)) as usize;
let now_slot = (now / self.slot_range) as usize;
let occupied = self.occupied.rotate_right(now_slot as u32);
let zeros = occupied.trailing_zeros() as usize;
let slot = (zeros + now_slot) % 64;
Expand Down
37 changes: 17 additions & 20 deletions monoio/src/time/driver/wheel/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ pub(crate) struct Wheel {
/// * ~ 4 min slots / ~ 4 hr range
/// * ~ 4 hr slots / ~ 12 day range
/// * ~ 12 day slots / ~ 2 yr range
levels: Vec<Level>,
levels: Box<[Level; NUM_LEVELS]>,

/// Entries queued for firing
pending: EntryList,
Expand All @@ -53,7 +53,14 @@ pub(super) const MAX_DURATION: u64 = (1 << (6 * NUM_LEVELS)) - 1;
impl Wheel {
/// Create a new timing wheel
pub(crate) fn new() -> Wheel {
let levels = (0..NUM_LEVELS).map(Level::new).collect();
let levels = Box::new([
Level::new(0),
Level::new(1),
Level::new(2),
Level::new(3),
Level::new(4),
Level::new(5),
]);

Wheel {
elapsed: 0,
Expand Down Expand Up @@ -103,11 +110,11 @@ impl Wheel {
let level = self.level_for(when);

unsafe {
self.levels[level].add_entry(item);
self.levels.get_unchecked_mut(level).add_entry(item);
}

debug_assert!({
self.levels[level]
unsafe { self.levels.get_unchecked(level) }
.next_expiration(self.elapsed)
.map(|e| e.deadline >= self.elapsed)
.unwrap_or(true)
Expand All @@ -132,7 +139,7 @@ impl Wheel {

let level = self.level_for(when);

self.levels[level].remove_entry(item);
self.levels.get_unchecked_mut(level).remove_entry(item);
}
}
}
Expand All @@ -149,23 +156,13 @@ impl Wheel {
return Some(handle);
}

// under what circumstances is poll.expiration Some vs. None?
let expiration = self.next_expiration().and_then(|expiration| {
if expiration.deadline > now {
None
} else {
Some(expiration)
}
});

match expiration {
Some(ref expiration) if expiration.deadline > now => return None,
Some(ref expiration) => {
match self.next_expiration() {
Some(ref expiration) if expiration.deadline <= now => {
self.process_expiration(expiration);

self.set_elapsed(expiration.deadline);
}
None => {
_ => {
// in this case the poll did not indicate an expiration
// _and_ we were not able to find a next expiration in
// the current list of timers. advance to the poll's
Expand Down Expand Up @@ -257,7 +254,7 @@ impl Wheel {
Err(expiration_tick) => {
let level = level_for(expiration.deadline, expiration_tick);
unsafe {
self.levels[level].add_entry(item);
self.levels.get_unchecked_mut(level).add_entry(item);
}
}
}
Expand All @@ -280,7 +277,7 @@ impl Wheel {
/// Obtains the list of entries that need processing for the given
/// expiration.
fn take_entries(&mut self, expiration: &Expiration) -> EntryList {
self.levels[expiration.level].take_slot(expiration.slot)
unsafe { self.levels.get_unchecked_mut(expiration.level) }.take_slot(expiration.slot)
}

fn level_for(&self, when: u64) -> usize {
Expand Down

0 comments on commit 9404c88

Please sign in to comment.