Commit d07aa05e authored by Andre Pinto's avatar Andre Pinto Committed by Pavlo Kushnir

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
parent 323c9a33
......@@ -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 \
......
......@@ -17,7 +17,7 @@
#include <cstdint>
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
......@@ -29,8 +29,8 @@
#include <folly/IntrusiveList.h>
#include <folly/futures/Try.h>
#include <folly/experimental/ExecutionObserver.h>
#include <folly/experimental/fibers/BoostContextCompatibility.h>
#include <folly/experimental/fibers/ExecutionObserver.h>
#include <folly/experimental/fibers/Fiber.h>
#include <folly/experimental/fibers/traits.h>
......
......@@ -155,7 +155,8 @@ EventBase::EventBase(bool enableTimeMeasurement)
, latestLoopCnt_(nextLoopCnt_)
, startWork_(0)
, observer_(nullptr)
, observerSampleCount_(0) {
, observerSampleCount_(0)
, executionObserver_(nullptr) {
{
std::lock_guard<std::mutex> 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");
......
......@@ -21,6 +21,7 @@
#include <folly/io/async/TimeoutManager.h>
#include <folly/io/async/Request.h>
#include <folly/Executor.h>
#include <folly/experimental/ExecutionObserver.h>
#include <folly/futures/DrivableExecutor.h>
#include <memory>
#include <stack>
......@@ -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<EventBaseObserver> observer_;
uint32_t observerSampleCount_;
// EventHandler's execution observer.
ExecutionObserver* executionObserver_;
// Name of the thread running this EventBase
std::string name_;
};
......
......@@ -147,10 +147,19 @@ void EventHandler::libeventCallback(int fd, short events, void* arg) {
EventHandler* handler = reinterpret_cast<EventHandler*>(arg);
assert(fd == handler->event_.ev_fd);
auto observer = handler->eventBase_->getExecutionObserver();
if (observer) {
observer->starting(reinterpret_cast<uintptr_t>(handler));
}
// this can't possibly fire if handler->eventBase_ is nullptr
(void) handler->eventBase_->bumpHandlingTime();
handler->handlerReady(events);
if (observer) {
observer->stopped(reinterpret_cast<uintptr_t>(handler));
}
}
void EventHandler::setEventBase(EventBase* eventBase) {
......
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