From: bert hubert Date: Mon, 1 Apr 2019 12:47:59 +0000 (+0200) Subject: This provides CPU usage statistics per thread (worker & distributor). X-Git-Tag: dnsdist-1.4.0-alpha1~18^2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=refs%2Fpull%2F7649%2Fhead;p=thirdparty%2Fpdns.git This provides CPU usage statistics per thread (worker & distributor). (cherry picked from commit 4ae78615a5a0fb0721ebe1a58a1235e75c47d400) --- diff --git a/pdns/pdns_recursor.cc b/pdns/pdns_recursor.cc index 231232248c..1c9f5746fc 100644 --- a/pdns/pdns_recursor.cc +++ b/pdns/pdns_recursor.cc @@ -3031,6 +3031,7 @@ template string broadcastAccFunction(const boost::function& fun); // template uint64_t broadcastAccFunction(const boost::function& fun); // explicit instantiation template vector broadcastAccFunction(const boost::function *()>& fun); // explicit instantiation template vector > broadcastAccFunction(const boost::function > *()>& fun); // explicit instantiation +template ThreadTimes broadcastAccFunction(const boost::function& fun); static void handleRCC(int fd, FDMultiplexer::funcparam_t& var) { diff --git a/pdns/rec_channel_rec.cc b/pdns/rec_channel_rec.cc index 453885bad4..77bbd872e8 100644 --- a/pdns/rec_channel_rec.cc +++ b/pdns/rec_channel_rec.cc @@ -762,6 +762,48 @@ static uint64_t getUserTimeMsec() return (ru.ru_utime.tv_sec*1000ULL + ru.ru_utime.tv_usec/1000); } +/* This is a pretty weird set of functions. To get per-thread cpu usage numbers, + we have to ask a thread over a pipe. We could do so surgically, so if you want to know about + thread 3, we pick pipe 3, but we lack that infrastructure. + + We can however ask "execute this function on all threads and add up the results". + This is what the first function does using a custom object ThreadTimes, which if you add + to each other keeps filling the first one with CPU usage numbers +*/ + +static ThreadTimes* pleaseGetThreadCPUMsec() +{ + uint64_t ret=0; +#ifdef RUSAGE_THREAD + struct rusage ru; + getrusage(RUSAGE_THREAD, &ru); + ret = (ru.ru_utime.tv_sec*1000ULL + ru.ru_utime.tv_usec/1000); + ret += (ru.ru_stime.tv_sec*1000ULL + ru.ru_stime.tv_usec/1000); +#endif + return new ThreadTimes{ret}; +} + +/* Next up, when you want msec data for a specific thread, we check + if we recently executed pleaseGetThreadCPUMsec. If we didn't we do so + now and consult all threads. + + We then answer you from the (re)fresh(ed) ThreadTimes. +*/ +static uint64_t doGetThreadCPUMsec(int n) +{ + static std::mutex s_mut; + static time_t last = 0; + static ThreadTimes tt; + + std::lock_guard l(s_mut); + if(last != time(nullptr)) { + tt = broadcastAccFunction(pleaseGetThreadCPUMsec); + last = time(nullptr); + } + + return tt.times.at(n); +} + static uint64_t calculateUptime() { return time(nullptr) - g_stats.startupTime; @@ -1082,6 +1124,9 @@ void registerAllStats() addGetStat("user-msec", getUserTimeMsec); addGetStat("sys-msec", getSysTimeMsec); + for(unsigned int n=0; n < g_numThreads; ++n) + addGetStat("cpu-msec-thread-"+std::to_string(n), boost::bind(&doGetThreadCPUMsec, n)); + #ifdef MALLOC_TRACE addGetStat("memory-allocs", boost::bind(&MallocTracer::getAllocs, g_mtracer, string())); addGetStat("memory-alloc-flux", boost::bind(&MallocTracer::getAllocFlux, g_mtracer, string())); diff --git a/pdns/recursordist/docs/metrics.rst b/pdns/recursordist/docs/metrics.rst index 1fbf805763..c04ebbc01f 100644 --- a/pdns/recursordist/docs/metrics.rst +++ b/pdns/recursordist/docs/metrics.rst @@ -185,6 +185,10 @@ concurrent-queries ^^^^^^^^^^^^^^^^^^ shows the number of MThreads currently running +cpu-msec-thread-n +^^^^^^^^^^^^^^^^^ +shows the number of milliseconds spent in thread n. Available since 4.1.12. + dlg-only-drops ^^^^^^^^^^^^^^ number of records dropped because of :ref:`setting-delegation-only` setting diff --git a/pdns/syncres.hh b/pdns/syncres.hh index bba453e2cf..e2562a1c2f 100644 --- a/pdns/syncres.hh +++ b/pdns/syncres.hh @@ -1037,3 +1037,14 @@ void doCarbonDump(void*); void primeHints(void); extern __thread struct timeval g_now; + +struct ThreadTimes +{ + uint64_t msec; + vector times; + ThreadTimes& operator+=(const ThreadTimes& rhs) + { + times.push_back(rhs.msec); + return *this; + } +};