Commit c73368f4 authored by Matthieu Martin's avatar Matthieu Martin Committed by Facebook Github Bot

Avoid unecessary RequestContext swap in FiberManager

Summary:
In my use case, at least, it's very likely that most Fibers are sharing the same RequestContext.
This could save a lot of onSet/onUnset calls.
Unsafe?

Reviewed By: andriigrynenko

Differential Revision: D9115679

fbshipit-source-id: 216208dff509c61b9f20f324c3e648ec79ebbaf7
parent f40a4d88
...@@ -112,7 +112,8 @@ inline void FiberManager::runReadyFiber(Fiber* fiber) { ...@@ -112,7 +112,8 @@ inline void FiberManager::runReadyFiber(Fiber* fiber) {
fiber->state_ == Fiber::NOT_STARTED || fiber->state_ == Fiber::NOT_STARTED ||
fiber->state_ == Fiber::READY_TO_RUN); fiber->state_ == Fiber::READY_TO_RUN);
currentFiber_ = fiber; currentFiber_ = fiber;
fiber->rcontext_ = RequestContext::setContext(std::move(fiber->rcontext_)); // Note: resetting the context is handled by the loop
RequestContext::setContext(std::move(fiber->rcontext_));
if (observer_) { if (observer_) {
observer_->starting(reinterpret_cast<uintptr_t>(fiber)); observer_->starting(reinterpret_cast<uintptr_t>(fiber));
} }
...@@ -138,7 +139,7 @@ inline void FiberManager::runReadyFiber(Fiber* fiber) { ...@@ -138,7 +139,7 @@ inline void FiberManager::runReadyFiber(Fiber* fiber) {
observer_->stopped(reinterpret_cast<uintptr_t>(fiber)); observer_->stopped(reinterpret_cast<uintptr_t>(fiber));
} }
currentFiber_ = nullptr; currentFiber_ = nullptr;
fiber->rcontext_ = RequestContext::setContext(std::move(fiber->rcontext_)); fiber->rcontext_ = RequestContext::saveContext();
} else if (fiber->state_ == Fiber::INVALID) { } else if (fiber->state_ == Fiber::INVALID) {
assert(fibersActive_ > 0); assert(fibersActive_ > 0);
--fibersActive_; --fibersActive_;
...@@ -160,7 +161,7 @@ inline void FiberManager::runReadyFiber(Fiber* fiber) { ...@@ -160,7 +161,7 @@ inline void FiberManager::runReadyFiber(Fiber* fiber) {
observer_->stopped(reinterpret_cast<uintptr_t>(fiber)); observer_->stopped(reinterpret_cast<uintptr_t>(fiber));
} }
currentFiber_ = nullptr; currentFiber_ = nullptr;
fiber->rcontext_ = RequestContext::setContext(std::move(fiber->rcontext_)); fiber->rcontext_ = RequestContext::saveContext();
fiber->localData_.reset(); fiber->localData_.reset();
fiber->rcontext_.reset(); fiber->rcontext_.reset();
...@@ -178,7 +179,7 @@ inline void FiberManager::runReadyFiber(Fiber* fiber) { ...@@ -178,7 +179,7 @@ inline void FiberManager::runReadyFiber(Fiber* fiber) {
observer_->stopped(reinterpret_cast<uintptr_t>(fiber)); observer_->stopped(reinterpret_cast<uintptr_t>(fiber));
} }
currentFiber_ = nullptr; currentFiber_ = nullptr;
fiber->rcontext_ = RequestContext::setContext(std::move(fiber->rcontext_)); fiber->rcontext_ = RequestContext::saveContext();
fiber->state_ = Fiber::READY_TO_RUN; fiber->state_ = Fiber::READY_TO_RUN;
yieldedFibers_.push_back(*fiber); yieldedFibers_.push_back(*fiber);
} }
...@@ -199,7 +200,13 @@ inline void FiberManager::loopUntilNoReadyImpl() { ...@@ -199,7 +200,13 @@ inline void FiberManager::loopUntilNoReadyImpl() {
auto originalFiberManager = this; auto originalFiberManager = this;
std::swap(currentFiberManager_, originalFiberManager); std::swap(currentFiberManager_, originalFiberManager);
// Save current context, and reset it after executing all fibers.
// This can avoid a lot of context swapping,
// if the Fibers share the same context
auto curCtx = RequestContext::saveContext();
SCOPE_EXIT { SCOPE_EXIT {
RequestContext::setContext(std::move(curCtx));
isLoopScheduled_ = false; isLoopScheduled_ = false;
if (!readyFibers_.empty()) { if (!readyFibers_.empty()) {
ensureLoopScheduled(); ensureLoopScheduled();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment