-
-
Notifications
You must be signed in to change notification settings - Fork 2.5k
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
time: avoid traversing entries in the time wheel twice #6718
base: master
Are you sure you want to change the base?
Conversation
cached_when
in TimerShared
What has changed since the original PR? Can you add a test for the previous bug? We probably won't merge this until we have #6717, but it still makes sense to add a dedicated test for the problem. |
…e" (tokio-rs#6715)" This reverts commit 47210a8.
3f7fcdc
to
cd70a24
Compare
} | ||
} | ||
lock.occupied_bit_maintain(&expiration); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The old code doesn't call this. Why is it necessary now?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The reason I add occupied_bit_maintain
now is that in the past, we would use take_entries
to take all items from the linked list at once and then update the occupied bit. But now, we need to traverse the items one by one, which means we need to update the occupied bit after the traversal is completed. I think the difference here is that in the current version, the linked list is not necessarily empty, so I add this method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it be accurate to say that this is an operation that must be called when we are done with list
? Would it make sense for it to be part of the destructor of EntryWaitersList
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does it need to be called before drop(lock)
in if !waker_list.can_push() {
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Calling occupied_bit_maintain
before drop(lock)
in if !waker_list.can_push() {
makes sense to me. That is a good idea.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about set_elapsed
?
I would really like to see a loom test where a timer is inserted during the if !waker_list.can_push() { ... }
block. It's hard for me to tell whether it's correct.
I think you can do the loom test along these lines:
- Start a runtime with paused time.
- Create and poll 32 timers with the timer.
- Spawn a thread. The background thread will create a timer, register it, and wait for it to complete.
- In parallel with that wait for the 32 timers in order.
- Join the background thread.
Spawning the thread after registering the 32 timers should reduce the size of the loom test, since the region with more than 1 thread will be shorter. As long as the if !waker_list.can_push() { ... }
block happens in the more-than-1-thread region of the test, it should work.
tokio/src/runtime/time/mod.rs
Outdated
} | ||
} | ||
} | ||
Err(state) if state == STATE_DEREGISTERED => {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can STATE_DEREGISTERED
actually happen?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No. I think it will not happen.
This is for reverting the
cached_when
in #6584In the
extend_expiration
method, we will not necessarily re-move the timer entry, but its state can be modified.So we use the
cached_when
to calculate which slot the timer entry is currently stored in.