19
19
#include <stdint.h>
27
26
#include <iostream>
29
27
#include <drizzled/session.h>
31
29
#define ONE_BILLION 1000000000ULL
32
30
#define ONE_MILLION 1000000
33
31
#define ONE_THOUSAND 1000
35
#define ENABLE_RTDC_BASED_TIMER
39
//Set this to 1, if you want to profile the code.
41
#define TIME_PROFILE_ON 1
44
#define _CONCAT(a,b) a ## b
45
#define CONCAT(a,b) _CONCAT(a, b)
35
47
namespace drizzled {
56
68
inline const char* getTimePrecToStr(int ePrecRange);
84
#ifdef TIME_PROFILE_ON
86
#define BLOCK_NANO_SEC_TIMER(sBlockName) drizzled::timer::FastTimerNanoSecPrec CONCAT(autoObj, __LINE__ )(sBlockName);
87
#define BLOCK_MICRO_SEC_TIMER(sBlockName) drizzled::timer::FastTimerMicroSecPrec CONCAT(autoObj, __LINE__ )(sBlockName);
88
#define BLOCK_MILLI_SEC_TIMER(sBlockName) drizzled::timer::FastTimerMilliSecPrec CONCAT(autoObj, __LINE__ )(sBlockName);
89
#define BLOCK_SEC_TIMER(sBlockName) drizzled::timer::FastTimerSecPrec CONCAT(autoObj, __LINE__ )(sBlockName);
91
#define START_PROFILING_PHASE(name, scale) \
92
drizzled::timer::th_pushProfilePhase(name, scale); \
93
drizzled::timer::AutoProfPhase autoPhase;
96
#define GET_ALL_PROFILING_RESULT(outputStream) drizzled::timer::thp().printAllOpTime(outputStream);
100
#define START_PROFILING_PHASE(name, scale)
101
#define END_PROFILING_AND_COLLECT_RESULT(outputStream)
102
#define BLOCK_NANO_SEC_TIMER(sBlockName)
103
#define BLOCK_MICRO_SEC_TIMER(sBlockName)
104
#define BLOCK_MILLI_SEC_TIMER(sBlockName)
105
#define BLOCK_SEC_TIMER(sBlockName)
106
#define GET_ALL_PROFILING_RESULT(outputStream)
59
112
class TimeProfile {
61
114
typedef std::pair<uint64_t, uint64_t> AccOccTimePair;
62
115
typedef std::map<std::string, AccOccTimePair> OpTimeMap;
66
118
TimeProfile():m_sProfName("{NoProfileName}"),
88
140
oss << "{" << std::endl;
89
141
while( itr != opTimeMap.end() ) {
90
142
oss << itr->first;
91
oss << ", acc= " << itr->second.first << " m_sScale";
143
oss << ", acc= " << itr->second.first << " " << m_sScale;
92
144
oss << ", occ=" << itr->second.second << std::endl;
123
176
timeProfileStack.pop();
179
void printAllOpTime(std::ostream& oss) {
180
while( !timeProfileStack.empty() ) {
181
timeProfileStack.top().printOpTime(oss);
183
timeProfileStack.pop();
185
std::vector<std::string>::const_iterator it = profileData.begin();
186
while(it != profileData.end()) {
194
void saveProfileData(const char* pData) {
195
std::string sStr(pData);
197
profileData.push_back(sStr);
126
TimeProfile timeProfile;
127
200
std::stack<TimeProfile> timeProfileStack;
201
std::vector<std::string> profileData;
130
205
inline ThreadProfile& thp() {
131
206
return current_session->getThreadProfile();
144
219
thp().popProfilePhase();
223
class AutoProfPhase {
225
explicit AutoProfPhase() { }
226
void popAndSaveProfileData() const {
227
std::stringstream ss;
229
th_getProf()->printOpTime(ss);
230
th_popProfilePhase();
231
thp().saveProfileData(ss.str().c_str());
235
popAndSaveProfileData();
147
240
namespace rtdcimpl {
149
242
inline uint64_t getTimeInNanoSec();
159
252
asm volatile("rdtsc":"=A"(curTimeCntr));
160
253
#elif defined(__GNUC__) && defined(__x86_64__)
162
asm volatile("rdtc":"=a"(hi), "=b"(lo));
255
asm volatile("rdtc":"=a"(hi), "=d"(lo));
163
256
curTimeCntr = (((uint64_t)hi << 32) || low);
183
276
double scale = (double)secondsToTest/deltaTime;
187
double processorrCounterScale = getProcTimerstampScale();
279
#ifdef ENABLE_RTDC_BASED_TIMER
280
static double processorrCounterScale = getProcTimerstampScale();
282
static double processorrCounterScale = 0;
189
284
inline uint64_t getTimeInSec() {
190
285
uint64_t procCounterValue = getProcTimestampCounter();
191
286
return procCounterValue * processorrCounterScale;
367
#if defined(__GNUC__) && defined(__i386__)
368
#define HAVE_RTDC_IMPL
369
#elif defined(__GNUC__) && defined(__x86_64__)
370
#define HAVE_RTDC_IMPL
286
373
inline bool useRtdcImpl() {
287
#if defined(__GNUC__) && defined(__i386__)
289
#elif defined(__GNUC__) && defined(__x86_64__)
374
#ifdef HAVE_RTDC_IMPL
339
template<int eImplKind = eRtdcImpl, int ePrecRange = eNanoSecPrec >
424
* Class to capture timing information for C/C++ block
425
* If opName is supplied, it adds this information to currect active Timing
427
* Following are some overhead information for this classes
428
* eImplKind = eRtdcImpl (~50 ns on 2.7 GHz intel machine), This went to
429
* average ~20 ns for large number of operations (1 million in my example)
430
* eImplKind = eClockTimeImpl (~1000 ns on 2.7 GHz intel machine)
431
* eImplKind = eGetToDImpl (~1500/2000 ns on 2.7 GHz intel machine)
433
template<int eImplKind , int ePrecRange >
340
434
class AutoOpTimer {
342
explicit AutoOpTimer(const char* sOpName):m_sOpName(sOpName) {
436
explicit AutoOpTimer(const char* sOpName):m_sOpName(sOpName)
439
// m_pTimeProf = thp().cur();
379
uint64_t release() const {
475
uint64_t getTimeElapsed() const {
380
476
uint64_t uCurTime = getCurTime();
381
477
uint64_t uDiff = (uCurTime - m_uBgnTime) * (uCurTime > m_uBgnTime);
386
uint64_t uTimeElapsed = release();
482
uint64_t uTimeElapsed = getTimeElapsed();
387
483
if( m_sOpName ) {
388
484
if( th_getProf() )
389
485
th_getProf()->addOpTime(m_sOpName, uTimeElapsed);
394
490
uint64_t m_uBgnTime;
399
#if defined(HAVE_RTDC)
493
//Rtdc based timer do not give reliable timing information.
494
//so by default they are off. One can use them directly if they want in
495
//CPU-bound operation by using following Rtdc Timers and setting
496
//ENABLE_RTDC_BASED_TIMER macro above.
497
typedef AutoOpTimer<eRtdcImpl, eNanoSecPrec> RtdcTimerNanoSecPrec;
498
typedef AutoOpTimer<eRtdcImpl, eMilliSecPrec> RtdcTimerMilliSecPrec;
499
typedef AutoOpTimer<eRtdcImpl, eMicroSecPrec> RtdcTimerMicroSecPrec;
500
typedef AutoOpTimer<eRtdcImpl, eSecPrec> RtdcTimerSecPrec;
503
#if defined(HAVE_RTDC_IMPL)
400
504
typedef AutoOpTimer<eRtdcImpl, eNanoSecPrec> FastTimerNanoSecPrec;
401
505
typedef AutoOpTimer<eRtdcImpl, eMilliSecPrec> FastTimerMilliSecPrec;
402
506
typedef AutoOpTimer<eRtdcImpl, eMicroSecPrec> FastTimerMicroSecPrec;
403
507
typedef AutoOpTimer<eRtdcImpl, eSecPrec> FastTimerSecPrec;
404
#elif defined(HAVE_CLOCK)
508
#elif defined(HAVE_CLOCK_GETTIME)
405
509
typedef AutoOpTimer<eClockTimeImpl, eNanoSecPrec> FastTimerNanoSecPrec;
406
510
typedef AutoOpTimer<eClockTimeImpl, eMilliSecPrec> FastTimerMilliSecPrec;
407
511
typedef AutoOpTimer<eClockTimeImpl, eMicroSecPrec> FastTimerMicroSecPrec;
413
517
typedef AutoOpTimer<eGetToDImpl, eSecPrec> FastTimerSecPrec;
521
uint64_t getSecTime() {
522
return FastTimerSecPrec::getCurTime();
525
uint64_t getMilliSecTime() {
526
return FastTimerMilliSecPrec::getCurTime();
529
uint64_t getMicroSecTime() {
530
return FastTimerMicroSecPrec::getCurTime();
533
uint64_t getNanoSecTime() {
534
return FastTimerNanoSecPrec::getCurTime();
417
538
#ifdef TEST_TIMER
497
618
void testTiming() {
500
debug() << "----------------------------------------" << endl;
501
debug() << "Testing get_clocktime based timer impl" << endl;
621
cerr << "----------------------------------------" << endl;
622
cerr << "Testing get_clocktime based timer impl" << endl;
502
623
using clockimpl::getTimeInNanoSec;
503
624
using clockimpl::getTimeInMilliSec;
504
625
using clockimpl::getTimeInMicroSec;
527
debug() << "----------------------------------------" << endl;
528
debug() << endl << "Testing gettimeofday based timer impl" << endl;
648
cerr << "----------------------------------------" << endl;
649
cerr << endl << "Testing gettimeofday based timer impl" << endl;
529
650
using todimpl::getTimeInNanoSec;
530
651
using todimpl::getTimeInMilliSec;
531
652
using todimpl::getTimeInMicroSec;
554
debug() << "----------------------------------------" << endl;
555
debug() << endl << "Testing rtdc based timer impl" << endl;
675
cerr << "----------------------------------------" << endl;
676
cerr << endl << "Testing rtdc based timer impl" << endl;
556
677
using rtdcimpl::getTimeInNanoSec;
557
678
using rtdcimpl::getTimeInMilliSec;
558
679
using rtdcimpl::getTimeInMicroSec;