From: Andre Pinto Date: Wed, 27 May 2015 02:06:05 +0000 (-0700) Subject: Instrument EventHandlers' execution X-Git-Tag: v0.41.0~3 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=d07aa05e1e690ef181c52eb3bd3e70198bddd47a;p=folly.git 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 --- 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/ExecutionObserver.h b/folly/experimental/ExecutionObserver.h new file mode 100644 index 00000000..1977d0c9 --- /dev/null +++ b/folly/experimental/ExecutionObserver.h @@ -0,0 +1,51 @@ +/* + * Copyright 2015 Facebook, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#pragma once + +#include + +namespace folly { + +/** + * Observes the execution of a task. + */ +class ExecutionObserver { + public: + virtual ~ExecutionObserver() { } + + /** + * Called when a task is about to start executing. + * + * @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 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 task which stopped. + */ + virtual void stopped(uintptr_t id) noexcept = 0; +}; + +} // namespace folly diff --git a/folly/experimental/fibers/ExecutionObserver.h b/folly/experimental/fibers/ExecutionObserver.h deleted file mode 100644 index ef5f8fb0..00000000 --- a/folly/experimental/fibers/ExecutionObserver.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2015 Facebook, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#pragma once - -#include - -namespace folly { namespace fibers { - -/** - * Observes the execution of a task. - */ -class ExecutionObserver { - public: - virtual ~ExecutionObserver() { } - - /** - * Called when a task is about to start executing. - * - * @param id Unique id for the fiber 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. - */ - 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. - */ - virtual void stopped(uintptr_t id) noexcept = 0; -}; - -}} // namespace folly::fibers 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) {