From d07aa05e1e690ef181c52eb3bd3e70198bddd47a Mon Sep 17 00:00:00 2001 From: Andre Pinto Date: Tue, 26 May 2015 19:06:05 -0700 Subject: [PATCH] Instrument EventHandlers' execution Summary: Add the option to instrument every EventHandler that runs in a EventBase. Test Plan: Unit tests Reviewed By: davejwatson@fb.com Subscribers: alikhtarov, folly-diffs@, yfeldblum, chalfant FB internal diff: D2044546 Tasks: 6958000 Signature: t1:2044546:1432221358:6500d6c1a6631d7a06a18e874d051f2ff3108e10 --- folly/Makefile.am | 2 +- .../{fibers => }/ExecutionObserver.h | 10 ++++----- folly/experimental/fibers/FiberManager.h | 2 +- folly/io/async/EventBase.cpp | 6 ++++-- folly/io/async/EventBase.h | 21 +++++++++++++++++++ folly/io/async/EventHandler.cpp | 9 ++++++++ 6 files changed, 41 insertions(+), 9 deletions(-) rename folly/experimental/{fibers => }/ExecutionObserver.h (81%) diff --git a/folly/Makefile.am b/folly/Makefile.am index 0602265e..38776bdb 100644 --- a/folly/Makefile.am +++ b/folly/Makefile.am @@ -71,6 +71,7 @@ nobase_follyinclude_HEADERS = \ EvictingCacheMap.h \ experimental/AutoTimer.h \ experimental/Bits.h \ + experimental/ExecutionObserver.h \ experimental/EliasFanoCoding.h \ experimental/EventCount.h \ experimental/fibers/AddTasks.h \ @@ -80,7 +81,6 @@ nobase_follyinclude_HEADERS = \ experimental/fibers/BoostContextCompatibility.h \ experimental/fibers/EventBaseLoopController.h \ experimental/fibers/EventBaseLoopController-inl.h \ - experimental/fibers/ExecutionObserver.h \ experimental/fibers/Fiber.h \ experimental/fibers/Fiber-inl.h \ experimental/fibers/FiberManager.h \ diff --git a/folly/experimental/fibers/ExecutionObserver.h b/folly/experimental/ExecutionObserver.h similarity index 81% rename from folly/experimental/fibers/ExecutionObserver.h rename to folly/experimental/ExecutionObserver.h index ef5f8fb0..1977d0c9 100644 --- a/folly/experimental/fibers/ExecutionObserver.h +++ b/folly/experimental/ExecutionObserver.h @@ -17,7 +17,7 @@ #include -namespace folly { namespace fibers { +namespace folly { /** * Observes the execution of a task. @@ -29,23 +29,23 @@ class ExecutionObserver { /** * Called when a task is about to start executing. * - * @param id Unique id for the fiber which is starting. + * @param id Unique id for the task which is starting. */ virtual void starting(uintptr_t id) noexcept = 0; /** * Called when a task is ready to run. * - * @param id Unique id for the fiber which is ready to run. + * @param id Unique id for the task which is ready to run. */ virtual void runnable(uintptr_t id) noexcept = 0; /** * Called just after a task stops executing. * - * @param id Unique id for the fiber which is stopping. + * @param id Unique id for the task which stopped. */ virtual void stopped(uintptr_t id) noexcept = 0; }; -}} // namespace folly::fibers +} // namespace folly diff --git a/folly/experimental/fibers/FiberManager.h b/folly/experimental/fibers/FiberManager.h index 468a06da..ecd1a900 100644 --- a/folly/experimental/fibers/FiberManager.h +++ b/folly/experimental/fibers/FiberManager.h @@ -29,8 +29,8 @@ #include #include +#include #include -#include #include #include diff --git a/folly/io/async/EventBase.cpp b/folly/io/async/EventBase.cpp index 73a6af57..a3e5bdc9 100644 --- a/folly/io/async/EventBase.cpp +++ b/folly/io/async/EventBase.cpp @@ -155,7 +155,8 @@ EventBase::EventBase(bool enableTimeMeasurement) , latestLoopCnt_(nextLoopCnt_) , startWork_(0) , observer_(nullptr) - , observerSampleCount_(0) { + , observerSampleCount_(0) + , executionObserver_(nullptr) { { std::lock_guard lock(libevent_mutex_); @@ -193,7 +194,8 @@ EventBase::EventBase(event_base* evb, bool enableTimeMeasurement) , latestLoopCnt_(nextLoopCnt_) , startWork_(0) , observer_(nullptr) - , observerSampleCount_(0) { + , observerSampleCount_(0) + , executionObserver_(nullptr) { if (UNLIKELY(evb_ == nullptr)) { LOG(ERROR) << "EventBase(): Pass nullptr as event base."; throw std::invalid_argument("EventBase(): event base cannot be nullptr"); diff --git a/folly/io/async/EventBase.h b/folly/io/async/EventBase.h index 3e28d294..843ab464 100644 --- a/folly/io/async/EventBase.h +++ b/folly/io/async/EventBase.h @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -545,6 +546,23 @@ bool runImmediatelyOrRunInEventBaseThreadAndWait(const Cob& fn); return observer_; } + /** + * Setup execution observation/instrumentation for every EventHandler + * executed in this EventBase. + * + * @param executionObserver EventHandle's execution observer. + */ + void setExecutionObserver(ExecutionObserver* observer) { + executionObserver_ = observer; + } + + /** + * Gets the execution observer associated with this EventBase. + */ + ExecutionObserver* getExecutionObserver() { + return executionObserver_; + } + /** * Set the name of the thread that runs this event base. */ @@ -702,6 +720,9 @@ bool runImmediatelyOrRunInEventBaseThreadAndWait(const Cob& fn); std::shared_ptr observer_; uint32_t observerSampleCount_; + // EventHandler's execution observer. + ExecutionObserver* executionObserver_; + // Name of the thread running this EventBase std::string name_; }; diff --git a/folly/io/async/EventHandler.cpp b/folly/io/async/EventHandler.cpp index 890bc83c..dcccfafb 100644 --- a/folly/io/async/EventHandler.cpp +++ b/folly/io/async/EventHandler.cpp @@ -147,10 +147,19 @@ void EventHandler::libeventCallback(int fd, short events, void* arg) { EventHandler* handler = reinterpret_cast(arg); assert(fd == handler->event_.ev_fd); + auto observer = handler->eventBase_->getExecutionObserver(); + if (observer) { + observer->starting(reinterpret_cast(handler)); + } + // this can't possibly fire if handler->eventBase_ is nullptr (void) handler->eventBase_->bumpHandlingTime(); handler->handlerReady(events); + + if (observer) { + observer->stopped(reinterpret_cast(handler)); + } } void EventHandler::setEventBase(EventBase* eventBase) { -- 2.34.1