ctkHighPrecisionTimer.h 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. /*=============================================================================
  2. Library: CTK
  3. Copyright (c) German Cancer Research Center,
  4. Division of Medical and Biological Informatics
  5. Licensed under the Apache License, Version 2.0 (the "License");
  6. you may not use this file except in compliance with the License.
  7. You may obtain a copy of the License at
  8. http://www.apache.org/licenses/LICENSE-2.0
  9. Unless required by applicable law or agreed to in writing, software
  10. distributed under the License is distributed on an "AS IS" BASIS,
  11. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. See the License for the specific language governing permissions and
  13. limitations under the License.
  14. =============================================================================*/
  15. #ifndef CTKHIGHPRECISIONTIMER_H
  16. #define CTKHIGHPRECISIONTIMER_H
  17. #include <qglobal.h>
  18. #undef _ctk_use_high_precision_timer_fallback
  19. #ifdef Q_OS_MAC
  20. #include <mach/mach_time.h>
  21. #elif defined(Q_OS_UNIX)
  22. #include <time.h>
  23. #include <unistd.h>
  24. #ifndef _POSIX_MONOTONIC_CLOCK
  25. #warning Monotonic clock support missing on this POSIX platform
  26. #define _ctk_use_high_precision_timer_fallback
  27. #endif
  28. #elif defined(Q_OS_WIN)
  29. #include <windows.h>
  30. #else
  31. #define _ctk_use_high_precision_timer_fallback
  32. #endif
  33. #ifdef _ctk_use_high_precision_timer_fallback
  34. #warning ctkHighPrecisionTimer is using the slower QTime fallback
  35. #include <QTime>
  36. #endif
  37. /**
  38. * \ingroup Core
  39. *
  40. *
  41. * @brief A fast and high precision timer.
  42. *
  43. * This class provides a fast and high precision timer depending on
  44. * platform specific API. It can be used as a QTime replacement for
  45. * runtime measurements with a minimal performance overhead.
  46. */
  47. class ctkHighPrecisionTimer {
  48. public:
  49. inline ctkHighPrecisionTimer();
  50. inline void start();
  51. inline qint64 elapsedMilli();
  52. inline qint64 elapsedMicro();
  53. private:
  54. // only used on MacOS, but needs to be defined in the .cpp file
  55. static double timeConvert;
  56. #ifdef _ctk_use_high_precision_timer_fallback
  57. QTime startTime;
  58. #elif defined(Q_OS_MAC)
  59. quint64 startTime;
  60. #elif defined(Q_OS_UNIX)
  61. timespec startTime;
  62. #elif defined(Q_OS_WIN)
  63. LARGE_INTEGER timerFrequency;
  64. LARGE_INTEGER startTime;
  65. #endif
  66. };
  67. #ifdef _ctk_use_high_precision_timer_fallback
  68. inline ctkHighPrecisionTimer::ctkHighPrecisionTimer()
  69. : startTime(QTime::currentTime())
  70. {
  71. }
  72. inline void ctkHighPrecisionTimer::start()
  73. {
  74. startTime = QTime::currentTime();
  75. }
  76. inline qint64 ctkHighPrecisionTimer::elapsedMilli()
  77. {
  78. return startTime.elapsed();
  79. }
  80. inline qint64 ctkHighPrecisionTimer::elapsedMicro()
  81. {
  82. return startTime.elapsed() * 1000;
  83. }
  84. #elif defined(Q_OS_MAC)
  85. inline ctkHighPrecisionTimer::ctkHighPrecisionTimer()
  86. : startTime(0)
  87. {
  88. if (timeConvert == 0)
  89. {
  90. mach_timebase_info_data_t timeBase;
  91. mach_timebase_info(&timeBase);
  92. timeConvert = static_cast<double>(timeBase.numer) / static_cast<double>(timeBase.denom) / 1000.0;
  93. }
  94. }
  95. inline void ctkHighPrecisionTimer::start()
  96. {
  97. startTime = mach_absolute_time();
  98. }
  99. inline qint64 ctkHighPrecisionTimer::elapsedMilli()
  100. {
  101. quint64 current = mach_absolute_time();
  102. return static_cast<double>(current - startTime) * timeConvert / 1000.0;
  103. }
  104. inline qint64 ctkHighPrecisionTimer::elapsedMicro()
  105. {
  106. quint64 current = mach_absolute_time();
  107. return static_cast<double>(current - startTime) * timeConvert;
  108. }
  109. #elif defined(Q_OS_UNIX)
  110. inline ctkHighPrecisionTimer::ctkHighPrecisionTimer()
  111. {
  112. startTime.tv_nsec = 0;
  113. startTime.tv_sec = 0;
  114. }
  115. inline void ctkHighPrecisionTimer::start()
  116. {
  117. clock_gettime(CLOCK_MONOTONIC, &startTime);
  118. }
  119. inline qint64 ctkHighPrecisionTimer::elapsedMilli()
  120. {
  121. timespec current;
  122. clock_gettime(CLOCK_MONOTONIC, &current);
  123. return (static_cast<qint64>(current.tv_sec)*1000 + current.tv_nsec/1000/1000) -
  124. (static_cast<qint64>(startTime.tv_sec)*1000 + startTime.tv_nsec/1000/1000);
  125. }
  126. inline qint64 ctkHighPrecisionTimer::elapsedMicro()
  127. {
  128. timespec current;
  129. clock_gettime(CLOCK_MONOTONIC, &current);
  130. return (static_cast<qint64>(current.tv_sec)*1000*1000 + current.tv_nsec/1000) -
  131. (static_cast<qint64>(startTime.tv_sec)*1000*1000 + startTime.tv_nsec/1000);
  132. }
  133. #elif defined(Q_OS_WIN)
  134. #include "ctkException.h"
  135. inline ctkHighPrecisionTimer::ctkHighPrecisionTimer()
  136. {
  137. if (!QueryPerformanceFrequency(&timerFrequency))
  138. throw ctkRuntimeException("QueryPerformanceFrequency() failed");
  139. }
  140. inline void ctkHighPrecisionTimer::start()
  141. {
  142. //DWORD_PTR oldmask = SetThreadAffinityMask(GetCurrentThread(), 0);
  143. QueryPerformanceCounter(&startTime);
  144. //SetThreadAffinityMask(GetCurrentThread(), oldmask);
  145. }
  146. inline qint64 ctkHighPrecisionTimer::elapsedMilli()
  147. {
  148. LARGE_INTEGER current;
  149. QueryPerformanceCounter(&current);
  150. return (current.QuadPart - startTime.QuadPart) / (timerFrequency.QuadPart / 1000);
  151. }
  152. inline qint64 ctkHighPrecisionTimer::elapsedMicro()
  153. {
  154. LARGE_INTEGER current;
  155. QueryPerformanceCounter(&current);
  156. return (current.QuadPart - startTime.QuadPart) / (timerFrequency.QuadPart / (1000*1000));
  157. }
  158. #endif
  159. #endif // CTKHIGHPRECISIONTIMER_H