Commit 2db01ebc authored by Misha Shneerson's avatar Misha Shneerson Committed by Facebook GitHub Bot

Add BPF task stats tracepoint to TM and CPU thread pool executor

Summary:
Allows attaching a BPF script to observe tasks behavior

Sample script, attaching those probes to a test binary (./buck-out/gen/common/services/cpp/test/thrift_2_async_server) is provided.

Reviewed By: yfeldblum

Differential Revision: D21526163

fbshipit-source-id: e976ddada1921c8c904d65aa9a558bbb45bf158f
parent 1d98189f
......@@ -115,7 +115,7 @@ void IOThreadPoolExecutor::add(
auto ioThread = pickThread();
auto task = Task(std::move(func), expiration, std::move(expireCallback));
auto wrappedFunc = [ioThread, task = std::move(task)]() mutable {
auto wrappedFunc = [this, ioThread, task = std::move(task)]() mutable {
runTask(ioThread, std::move(task));
ioThread->pendingTasks--;
};
......
......@@ -18,6 +18,7 @@
#include <folly/executors/GlobalThreadPoolList.h>
#include <folly/synchronization/AsymmetricMemoryBarrier.h>
#include <folly/tracing/StaticTracepoint.h>
namespace folly {
......@@ -54,7 +55,9 @@ ThreadPoolExecutor::ThreadPoolExecutor(
taskStatsCallbacks_(std::make_shared<TaskStatsCallbackRegistry>()),
threadPoolHook_("folly::ThreadPoolExecutor"),
minThreads_(minThreads),
threadTimeout_(FLAGS_threadtimeout_ms) {}
threadTimeout_(FLAGS_threadtimeout_ms) {
namePrefix_ = getNameHelper();
}
ThreadPoolExecutor::~ThreadPoolExecutor() {
joinKeepAliveOnce();
......@@ -102,6 +105,21 @@ void ThreadPoolExecutor::runTask(const ThreadPtr& thread, Task&& task) {
}
stats.runTime = std::chrono::steady_clock::now() - startTime;
}
// Times in this USDT use granularity of std::chrono::steady_clock::duration,
// which is platform dependent. On Facebook servers, the granularity is
// nanoseconds. We explicitly do not perform any unit conversions to avoid
// unneccessary costs and leave it to consumers of this data to know what
// effective clock resolution is.
FOLLY_SDT(
folly,
thread_pool_executor_task_stats,
namePrefix_.c_str(),
stats.requestId,
stats.enqueueTime.time_since_epoch().count(),
stats.waitTime.count(),
stats.runTime.count());
thread->idle = true;
thread->lastActiveTime = std::chrono::steady_clock::now();
thread->taskStatsCallbacks->callbackList.withRLock([&](auto& callbacks) {
......@@ -301,12 +319,15 @@ size_t ThreadPoolExecutor::getPendingTaskCount() const {
return getPendingTaskCountImpl();
}
std::string ThreadPoolExecutor::getName() const {
const std::string& ThreadPoolExecutor::getName() const {
return namePrefix_;
}
std::string ThreadPoolExecutor::getNameHelper() const {
auto ntf = dynamic_cast<NamedThreadFactory*>(threadFactory_.get());
if (ntf == nullptr) {
return folly::demangle(typeid(*this).name()).toStdString();
}
return ntf->getNamePrefix();
}
......
......@@ -80,6 +80,7 @@ class ThreadPoolExecutor : public DefaultKeepAliveExecutor {
void setThreadFactory(std::shared_ptr<ThreadFactory> threadFactory) {
CHECK(numThreads() == 0);
threadFactory_ = std::move(threadFactory);
namePrefix_ = getNameHelper();
}
std::shared_ptr<ThreadFactory> getThreadFactory() const {
......@@ -122,7 +123,7 @@ class ThreadPoolExecutor : public DefaultKeepAliveExecutor {
PoolStats getPoolStats() const;
size_t getPendingTaskCount() const;
std::string getName() const;
const std::string& getName() const;
struct TaskStats {
TaskStats() : expired(false), waitTime(0), runTime(0), requestId(0) {}
......@@ -212,7 +213,7 @@ class ThreadPoolExecutor : public DefaultKeepAliveExecutor {
std::shared_ptr<folly::RequestContext> context_;
};
static void runTask(const ThreadPtr& thread, Task&& task);
void runTask(const ThreadPtr& thread, Task&& task);
// The function that will be bound to pool threads. It must call
// thread->startupBaton.post() when it's ready to consume work.
......@@ -298,7 +299,10 @@ class ThreadPoolExecutor : public DefaultKeepAliveExecutor {
std::queue<ThreadPtr> queue_;
};
std::string getNameHelper() const;
std::shared_ptr<ThreadFactory> threadFactory_;
std::string namePrefix_;
const bool isWaitForAll_; // whether to wait till event base loop exits
ThreadList threadList_;
......
......@@ -45,7 +45,7 @@ class NamedThreadFactory : public ThreadFactory {
prefix_ = prefix.str();
}
std::string getNamePrefix() {
const std::string& getNamePrefix() {
return prefix_;
}
......
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