Commit 621cc26e authored by James Sedgwick's avatar James Sedgwick Committed by facebook-github-bot-9

use HHWheelTimer for EventBase::runAfterDelay

Summary: For the perfs - big improvement on one fd per timeout.

Reviewed By: @djwatson, @fugalh

Differential Revision: D2379210
parent 60331af0
...@@ -123,7 +123,13 @@ void EventBase::CobTimeout::timeoutExpired() noexcept { ...@@ -123,7 +123,13 @@ void EventBase::CobTimeout::timeoutExpired() noexcept {
} }
// The CobTimeout object was allocated on the heap by runAfterDelay(), // The CobTimeout object was allocated on the heap by runAfterDelay(),
// so delete it now that the it has fired. // so delete it now that it has fired.
delete this;
}
void EventBase::CobTimeout::callbackCanceled() noexcept {
// The CobTimeout object was allocated on the heap by runAfterDelay(),
// so delete it now that it has been canceled.
delete this; delete this;
} }
...@@ -175,6 +181,7 @@ EventBase::EventBase(bool enableTimeMeasurement) ...@@ -175,6 +181,7 @@ EventBase::EventBase(bool enableTimeMeasurement)
} }
VLOG(5) << "EventBase(): Created."; VLOG(5) << "EventBase(): Created.";
initNotificationQueue(); initNotificationQueue();
wheelTimer_ = HHWheelTimer::UniquePtr(new HHWheelTimer(this));
RequestContext::saveContext(); RequestContext::saveContext();
} }
...@@ -201,6 +208,7 @@ EventBase::EventBase(event_base* evb, bool enableTimeMeasurement) ...@@ -201,6 +208,7 @@ EventBase::EventBase(event_base* evb, bool enableTimeMeasurement)
throw std::invalid_argument("EventBase(): event base cannot be nullptr"); throw std::invalid_argument("EventBase(): event base cannot be nullptr");
} }
initNotificationQueue(); initNotificationQueue();
wheelTimer_ = HHWheelTimer::UniquePtr(new HHWheelTimer(this));
RequestContext::saveContext(); RequestContext::saveContext();
} }
...@@ -216,10 +224,7 @@ EventBase::~EventBase() { ...@@ -216,10 +224,7 @@ EventBase::~EventBase() {
// (Note that we don't fire them. The caller is responsible for cleaning up // (Note that we don't fire them. The caller is responsible for cleaning up
// its own data structures if it destroys the EventBase with unfired events // its own data structures if it destroys the EventBase with unfired events
// remaining.) // remaining.)
while (!pendingCobTimeouts_.empty()) { wheelTimer_->cancelAll();
CobTimeout* timeout = &pendingCobTimeouts_.front();
delete timeout;
}
while (!runBeforeLoopCallbacks_.empty()) { while (!runBeforeLoopCallbacks_.empty()) {
delete &runBeforeLoopCallbacks_.front(); delete &runBeforeLoopCallbacks_.front();
...@@ -654,12 +659,11 @@ void EventBase::runAfterDelay(const Cob& cob, ...@@ -654,12 +659,11 @@ void EventBase::runAfterDelay(const Cob& cob,
bool EventBase::tryRunAfterDelay(const Cob& cob, bool EventBase::tryRunAfterDelay(const Cob& cob,
int milliseconds, int milliseconds,
TimeoutManager::InternalEnum in) { TimeoutManager::InternalEnum in) {
CobTimeout* timeout = new CobTimeout(this, cob, in); // A previous implementation could fail, and the API is retained for
if (!timeout->scheduleTimeout(milliseconds)) { // backwards compatibility.
delete timeout; wheelTimer_->scheduleTimeout(
return false; new CobTimeout(cob),
} std::chrono::milliseconds(milliseconds));
pendingCobTimeouts_.push_back(*timeout);
return true; return true;
} }
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <glog/logging.h> #include <glog/logging.h>
#include <folly/io/async/AsyncTimeout.h> #include <folly/io/async/AsyncTimeout.h>
#include <folly/io/async/HHWheelTimer.h>
#include <folly/io/async/TimeoutManager.h> #include <folly/io/async/TimeoutManager.h>
#include <folly/io/async/Request.h> #include <folly/io/async/Request.h>
#include <folly/Executor.h> #include <folly/Executor.h>
...@@ -649,26 +650,16 @@ class EventBase : private boost::noncopyable, ...@@ -649,26 +650,16 @@ class EventBase : private boost::noncopyable,
// small object used as a callback arg with enough info to execute the // small object used as a callback arg with enough info to execute the
// appropriate client-provided Cob // appropriate client-provided Cob
class CobTimeout : public AsyncTimeout { class CobTimeout : public HHWheelTimer::Callback {
public: public:
CobTimeout(EventBase* b, const Cob& c, TimeoutManager::InternalEnum in) explicit CobTimeout(const Cob& c) : cob_(c) {}
: AsyncTimeout(b, in), cob_(c) {}
virtual void timeoutExpired() noexcept; void timeoutExpired() noexcept override;
void callbackCanceled() noexcept override;
private: private:
Cob cob_; Cob cob_;
public:
typedef boost::intrusive::list_member_hook<
boost::intrusive::link_mode<boost::intrusive::auto_unlink> > ListHook;
ListHook hook;
typedef boost::intrusive::list<
CobTimeout,
boost::intrusive::member_hook<CobTimeout, ListHook, &CobTimeout::hook>,
boost::intrusive::constant_time_size<false> > List;
}; };
typedef LoopCallback::List LoopCallbackList; typedef LoopCallback::List LoopCallbackList;
...@@ -681,7 +672,7 @@ class EventBase : private boost::noncopyable, ...@@ -681,7 +672,7 @@ class EventBase : private boost::noncopyable,
void initNotificationQueue(); void initNotificationQueue();
CobTimeout::List pendingCobTimeouts_; HHWheelTimer::UniquePtr wheelTimer_;
LoopCallbackList loopCallbacks_; LoopCallbackList loopCallbacks_;
LoopCallbackList runBeforeLoopCallbacks_; LoopCallbackList runBeforeLoopCallbacks_;
......
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