diff --git a/primitives/primproc/batchprimitiveprocessor.cpp b/primitives/primproc/batchprimitiveprocessor.cpp index e2291da1a..9e600e94d 100644 --- a/primitives/primproc/batchprimitiveprocessor.cpp +++ b/primitives/primproc/batchprimitiveprocessor.cpp @@ -70,6 +70,11 @@ using namespace joblist; namespace primitiveprocessor { + +#ifdef PRIMPROC_STOPWATCH +#include "poormanprofiler.inc" +#endif + // these are config parms defined in primitiveserver.cpp, initialized by PrimProc main(). extern uint32_t blocksReadAhead; extern uint32_t dictBufferSize; @@ -2157,42 +2162,14 @@ int BatchPrimitiveProcessor::operator()() utils::setThreadName("PPBatchPrimProc"); #ifdef PRIMPROC_STOPWATCH const static std::string msg{"BatchPrimitiveProcessor::operator()"}; - logging::StopWatch* stopwatch = nullptr; + logging::StopWatch* stopwatch = profiler.getTimer(); #endif if (currentBlockOffset == 0) { #ifdef PRIMPROC_STOPWATCH - auto stopwatchMapIter = stopwatchMap.find(pthread_self()); - - if (stopwatchMapIter != stopwatchMap.end()) - { - stopwatch = stopwatchMapIter->second; - } - else - { - pthread_mutex_lock(&stopwatchMapMutex); - stopwatch = new logging::StopWatch(stopwatchMap.size()); - stopwatchMap.insert({pthread_self(), stopwatch}); - - // Create the thread that will show timing results after five seconds of idle time. - if (!stopwatchThreadCreated) - { - pthread_t timerThread; - int err = pthread_create(&timerThread, NULL, autoFinishStopwatchThread, NULL); - - if (err) - cout << "Error creating thread to complete Stopwatches." << endl; - - stopwatchThreadCreated = true; - } - - pthread_mutex_unlock(&stopwatchMapMutex); - } - stopwatch->start(msg); #endif - idbassert(count > 0); } @@ -2272,7 +2249,6 @@ int BatchPrimitiveProcessor::operator()() << " blockNum=" << blockNum << endl; */ } - vssCache.clear(); #ifndef __FreeBSD__ pthread_mutex_unlock(&objLock); diff --git a/primitives/primproc/batchprimitiveprocessor.h b/primitives/primproc/batchprimitiveprocessor.h index 0c981cc75..27e7f97a9 100644 --- a/primitives/primproc/batchprimitiveprocessor.h +++ b/primitives/primproc/batchprimitiveprocessor.h @@ -54,6 +54,11 @@ #include "bppsendthread.h" #include "columnwidth.h" +//#define PRIMPROC_STOPWATCH +#ifdef PRIMPROC_STOPWATCH +#include "stopwatch.h" +#endif + namespace primitiveprocessor { typedef std::tr1::unordered_map VSSCache; diff --git a/primitives/primproc/primitiveserver.cpp b/primitives/primproc/primitiveserver.cpp index 5faddf35d..719893abb 100644 --- a/primitives/primproc/primitiveserver.cpp +++ b/primitives/primproc/primitiveserver.cpp @@ -2627,93 +2627,6 @@ bool BPPV::aborted() return sendThread->aborted(); } -#ifdef PRIMPROC_STOPWATCH -std::unordered_map stopwatchMap; -pthread_mutex_t stopwatchMapMutex; -bool stopwatchThreadCreated = false; - -//------------------------------------------------------------------------------ -// Stays in "sleep" state for specified until passed seconds have elapsed. -//------------------------------------------------------------------------------ -void pause_(int seconds ) -{ - struct timespec req; - struct timespec rem; - req.tv_sec = seconds; - req.tv_nsec = 0; - rem.tv_sec = 0; - rem.tv_nsec = 0; - - while (1) - { - if (nanosleep(&req, &rem) != 0) - { - if (rem.tv_sec > 0 || rem.tv_nsec > 0) - { - req = rem; - continue; - } - } - - break; - } -} - -void* autoFinishStopwatchThread(void* arg) -{ - struct timeval tvCurrent; - int count = 0; - - for (;;) - { - // Pause two seconds. - pause_(2); - count++; - // Iterate through the stopwatch map and see how long it's been since last activity. - auto stopwatchMapIter = stopwatchMap.begin(); - logging::StopWatch* stopwatch; - gettimeofday(&tvCurrent, 0); - bool primProcIdle = true; - - while (stopwatchMapIter != stopwatchMap.end()) - { - stopwatch = stopwatchMapIter->second; - - // If any threads have been active in the last 5 seconds, kick out. - if (((tvCurrent.tv_sec - stopwatch->fTvLast.tv_sec) < 5) || stopwatch->isActive()) - { - primProcIdle = false; - break; - } - - stopwatchMapIter++; - } - - // No activity in last five seconds, display timing results. - // if(primProcIdle || (count%15 == 0)) - if (primProcIdle) - { - pthread_mutex_lock(&stopwatchMapMutex); - stopwatchMapIter = stopwatchMap.begin(); - - while (stopwatchMapIter != stopwatchMap.end()) - { - stopwatch = stopwatchMapIter->second; - stopwatch->finish(); - stopwatchMapIter++; - delete stopwatch; - } - - stopwatchMap.clear(); - pthread_mutex_unlock(&stopwatchMapMutex); - } - } - - return 0; -}; -#endif // PRIMPROC_STOPWATCH - - // end workaround } // namespace primitiveprocessor diff --git a/primitives/primproc/primitiveserver.h b/primitives/primproc/primitiveserver.h index 5d423c34f..648cda187 100644 --- a/primitives/primproc/primitiveserver.h +++ b/primitives/primproc/primitiveserver.h @@ -44,11 +44,6 @@ #include "service.h" -//#define PRIMPROC_STOPWATCH -#ifdef PRIMPROC_STOPWATCH -#include "stopwatch.h" -#endif - #include "oamcache.h" extern oam::OamCache* oamCache; @@ -60,15 +55,6 @@ extern BRM::DBRM* brm; extern boost::mutex bppLock; extern uint32_t highPriorityThreads, medPriorityThreads, lowPriorityThreads; -#ifdef PRIMPROC_STOPWATCH -extern std::unordered_map stopwatchMap; -extern pthread_mutex_t stopwatchMapMutex; -extern bool stopwatchThreadCreated; - -extern void pause_(int seconds); -extern void* autoFinishStopwatchThread(void* arg); -#endif - class BPPV { public: diff --git a/utils/loggingcpp/poormanprofiler.inc b/utils/loggingcpp/poormanprofiler.inc new file mode 100644 index 000000000..68eac937e --- /dev/null +++ b/utils/loggingcpp/poormanprofiler.inc @@ -0,0 +1,140 @@ +#ifndef POORMANPROFILER_H +#define POORMANPROFILER_H + +#include "stopwatch.h" +#include +using StopWatchMapType = std::unordered_map; + +void pause_(int seconds ) +{ + struct timespec req; + struct timespec rem; + req.tv_sec = seconds; + req.tv_nsec = 0; + rem.tv_sec = 0; + rem.tv_nsec = 0; + + while (1) + { + if (nanosleep(&req, &rem) != 0) + { + if (rem.tv_sec > 0 || rem.tv_nsec > 0) + { + req = rem; + continue; + } + } + + break; + } +} + +class PoorManProfiler +{ + public: + PoorManProfiler() {}; + StopWatchMapType stopwatchMap; + pthread_mutex_t stopwatchMapMutex; + pthread_t timerThread; + bool stopwatchThreadCreated = false; + inline logging::StopWatch* start(); + inline logging::StopWatch* getTimer(); + inline void spawnAutoFinishThread(); +}; + +void* autoFinishStopwatchThread(void* arg) +{ + struct timeval tvCurrent; + + PoorManProfiler* profiler = reinterpret_cast(arg); + StopWatchMapType& stopwatchMap = profiler->stopwatchMap; + + for (;;) + { + // Pause n seconds. + pause_(10); + // Iterate through the stopwatch map and see how long it's been since last activity. + pthread_mutex_lock(&profiler->stopwatchMapMutex); + auto stopwatchMapIter = stopwatchMap.begin(); + logging::StopWatch* stopwatch; + gettimeofday(&tvCurrent, 0); + bool procIsIdle = true; + + while (stopwatchMapIter != stopwatchMap.end()) + { + stopwatch = stopwatchMapIter->second; + + // If any threads have been active in the last 5 seconds, kick out. + if (((tvCurrent.tv_sec - stopwatch->fTvLast.tv_sec) < 5) || stopwatch->isActive()) + { + procIsIdle = false; + break; + } + + stopwatchMapIter++; + } + + // No activity in last five seconds, display timing results. + if (procIsIdle) + { + stopwatchMapIter = stopwatchMap.begin(); + + while (stopwatchMapIter != stopwatchMap.end()) + { + stopwatch = stopwatchMapIter->second; + stopwatch->finish(); + stopwatchMapIter++; + delete stopwatch; + } + + stopwatchMap.clear(); + profiler->stopwatchThreadCreated = false; + } + pthread_mutex_unlock(&profiler->stopwatchMapMutex); + } + + return 0; +}; + +inline void PoorManProfiler::spawnAutoFinishThread() +{ + // Create the thread that will show timing results after five seconds of idle time. + if (!stopwatchThreadCreated) + { + pthread_t timerThread; + int err = pthread_create(&timerThread, nullptr, autoFinishStopwatchThread, this); + + if (err) + std::cerr << "Error creating thread to complete Stopwatches." << endl; + + stopwatchThreadCreated = true; + } +} + +inline logging::StopWatch* PoorManProfiler::start() +{ + pthread_mutex_lock(&stopwatchMapMutex); + auto stopwatchMapIter = stopwatchMap.find(pthread_self()); + + if (stopwatchMapIter != stopwatchMap.end()) + { + pthread_mutex_unlock(&stopwatchMapMutex); + return stopwatchMapIter->second; + } + logging::StopWatch* stopwatch = new logging::StopWatch(stopwatchMap.size()); + stopwatchMap.insert({pthread_self(), stopwatch}); + + spawnAutoFinishThread(); + + pthread_mutex_unlock(&stopwatchMapMutex); + return stopwatch; +} + +inline logging::StopWatch* PoorManProfiler::getTimer() +{ + return start(); +} + +static PoorManProfiler profiler; + +#endif