main_clock.cpp 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. #include <chrono>
  2. #include <thread>
  3. #include <vector>
  4. #include <iostream>
  5. #include <condition_variable>
  6. #include <cstdlib>
  7. #include <math.h>
  8. #include <type_traits>
  9. #include <unistd.h>
  10. #include <sys/syscall.h>
  11. #include <sys/time.h>
  12. static inline uint64_t getCurrentTime()
  13. {
  14. #if defined(__i386__)
  15. int64_t ret;
  16. __asm__ volatile("rdtsc" : "=A"(ret));
  17. return ret;
  18. #elif defined(__x86_64__) || defined(__amd64__)
  19. uint64_t low, high;
  20. __asm__ volatile("rdtsc" : "=a"(low), "=d"(high));
  21. return (high << 32) | low;
  22. #endif
  23. }
  24. int OBJECTS = 500;
  25. #define STR(x) #x
  26. int64_t calculate_cpu_frequency()//per sec
  27. {
  28. double g_TicksPerNanoSec;
  29. struct timespec begints, endts;
  30. uint64_t begin = 0, end = 0;
  31. clock_gettime(CLOCK_MONOTONIC, &begints);
  32. begin = getCurrentTime();
  33. volatile uint64_t i;
  34. for (i = 0; i < 100000000; i++); /* must be CPU intensive */
  35. end = getCurrentTime();
  36. clock_gettime(CLOCK_MONOTONIC, &endts);
  37. struct timespec tmpts;
  38. const int NANO_SECONDS_IN_SEC = 1000000000;
  39. tmpts.tv_sec = endts.tv_sec - begints.tv_sec;
  40. tmpts.tv_nsec = endts.tv_nsec - begints.tv_nsec;
  41. if (tmpts.tv_nsec < 0)
  42. {
  43. tmpts.tv_sec--;
  44. tmpts.tv_nsec += NANO_SECONDS_IN_SEC;
  45. }
  46. uint64_t nsecElapsed = tmpts.tv_sec * 1000000000LL + tmpts.tv_nsec;
  47. g_TicksPerNanoSec = (double)(end - begin) / (double)nsecElapsed;
  48. int64_t cpu_frequency = int(g_TicksPerNanoSec * 1000);
  49. return cpu_frequency;
  50. }
  51. const auto CPU_FREQUENCY = calculate_cpu_frequency();
  52. # define TICKS_TO_US(ticks) ticks / CPU_FREQUENCY
  53. void localSleep(int magic=200000)
  54. {
  55. volatile int i = 0;
  56. for (; i < magic; ++i);
  57. }
  58. template<class Clock>
  59. auto calcDelta(int magic=200000) -> decltype(Clock::now().time_since_epoch().count())
  60. {
  61. auto start = Clock::now().time_since_epoch().count();
  62. localSleep(magic);
  63. auto end = Clock::now().time_since_epoch().count();
  64. return end - start;
  65. }
  66. template<class Clock>
  67. double calcDuration(int objects)
  68. {
  69. const auto frequency = Clock::period::den / Clock::period::num;
  70. auto start = Clock::now();
  71. decltype(Clock::now().time_since_epoch().count()) summ = 0;
  72. for (int i=0; i < objects; i++)
  73. {
  74. summ += calcDelta<Clock>();
  75. }
  76. summ = summ * 1000000LL / frequency;
  77. auto end = Clock::now();
  78. auto elapsed =
  79. std::chrono::duration_cast<std::chrono::microseconds>(end - start);
  80. return (elapsed.count()-summ)/double(objects)/2.0;
  81. }
  82. uint64_t calcDeltaRdtsc(int magic=200000)
  83. {
  84. auto start = getCurrentTime();
  85. localSleep(magic);
  86. auto end = getCurrentTime();
  87. return end - start;
  88. }
  89. double calcDurationByRdtsc(int objects)
  90. {
  91. auto start = getCurrentTime();
  92. uint64_t summ = 0;
  93. for (int i=0; i < objects; i++)
  94. {
  95. summ += calcDeltaRdtsc();
  96. }
  97. auto end = getCurrentTime();
  98. return TICKS_TO_US((end - start - summ))/double(objects)/2.0;
  99. }
  100. uint64_t calcDeltaSysCall(int magic, int type)
  101. {
  102. timespec tp0,tp1;
  103. syscall(SYS_clock_gettime, type, &tp0);
  104. auto start = tp0.tv_sec*1000000000+tp0.tv_nsec;
  105. localSleep(magic);
  106. syscall(SYS_clock_gettime, type, &tp1);
  107. auto end = tp1.tv_sec*1000000000+tp1.tv_nsec;
  108. return end - start;
  109. }
  110. double calcDurationBySyscall(int objects, int type)
  111. {
  112. timespec tp0,tp1;
  113. syscall(SYS_clock_gettime, type, &tp0);
  114. auto start = tp0.tv_sec*1000000000+tp0.tv_nsec;
  115. uint64_t summ = 0;
  116. for (int i=0; i < objects; i++)
  117. {
  118. summ += calcDeltaSysCall(200000,type);
  119. }
  120. syscall(SYS_clock_gettime, type, &tp1);
  121. auto end = tp1.tv_sec*1000000000+tp1.tv_nsec;
  122. return (end - start - summ)/double(objects)/2.0/1000.0;
  123. }
  124. uint64_t calcDeltaSysGetTime(int magic, int type)
  125. {
  126. timespec tp0,tp1;
  127. clock_gettime(type, &tp0);
  128. auto start = tp0.tv_sec*1000000000+tp0.tv_nsec;
  129. localSleep(magic);
  130. clock_gettime(type, &tp1);
  131. auto end = tp1.tv_sec*1000000000+tp1.tv_nsec;
  132. return end - start;
  133. }
  134. double calcDurationByGetTime(int objects, int type)
  135. {
  136. timespec tp0,tp1;
  137. clock_gettime(type, &tp0);
  138. auto start = tp0.tv_sec*1000000000+tp0.tv_nsec;
  139. uint64_t summ = 0;
  140. for (int i=0; i < objects; i++)
  141. {
  142. summ += calcDeltaSysGetTime(200000,type);
  143. }
  144. clock_gettime(type, &tp1);
  145. auto end = tp1.tv_sec*1000000000+tp1.tv_nsec;
  146. return (end - start - summ)/double(objects)/2.0/1000.0;
  147. }
  148. uint64_t calcDeltaSysGetTimeOfDay(int magic=200000)
  149. {
  150. timeval tv0,tv1;
  151. gettimeofday(&tv0,0);
  152. auto start = tv0.tv_sec*1000000+tv0.tv_usec;
  153. localSleep(magic);
  154. gettimeofday(&tv1, 0);
  155. auto end = tv1.tv_sec*1000000+tv1.tv_usec;
  156. return end - start;
  157. }
  158. double calcDurationByGetTimeOfDay(int objects)
  159. {
  160. timeval tv0,tv1;
  161. gettimeofday(&tv0,0);
  162. auto start = tv0.tv_sec*1000000+tv0.tv_usec;
  163. uint64_t summ = 0;
  164. for (int i=0; i < objects; i++)
  165. {
  166. summ += calcDeltaSysGetTimeOfDay();
  167. }
  168. gettimeofday(&tv1, 0);
  169. auto end = tv1.tv_sec*1000000+tv1.tv_usec;
  170. return (end - start - summ)/double(objects)/2.0;
  171. }
  172. int main(int argc, char* argv[])
  173. {
  174. if (argc > 1 && argv[1]){
  175. OBJECTS = std::atoi(argv[1]);
  176. }
  177. std::cout << STR(std::chrono::steady_clock) << ": "<<calcDuration<std::chrono::steady_clock>(OBJECTS) << " usec\n";
  178. std::cout << STR(std::chrono::high_resolution_clock)<< ": " << calcDuration<std::chrono::high_resolution_clock>(OBJECTS) << " usec\n";
  179. std::cout << STR(std::chrono::system_clock)<< ": " << calcDuration<std::chrono::system_clock>(OBJECTS) << " usec\n";
  180. std::cout << "\n";
  181. std::cout << "rdtsc: " << calcDurationByRdtsc(OBJECTS) << " usec\n";
  182. std::cout << "\n";
  183. std::cout << "syscall(SYS_clock_gettime, CLOCK_MONOTONIC): " << calcDurationBySyscall(OBJECTS,CLOCK_MONOTONIC) << " usec\n";
  184. std::cout << "syscall(SYS_clock_gettime, CLOCK_REALTIME): " << calcDurationBySyscall(OBJECTS,CLOCK_REALTIME) << " usec\n";
  185. std::cout << "syscall(SYS_clock_gettime, CLOCK_MONOTONIC_RAW): " << calcDurationBySyscall(OBJECTS,CLOCK_MONOTONIC_RAW) << " usec\n";
  186. std::cout << "syscall(SYS_clock_gettime, CLOCK_MONOTONIC_COARSE): " << calcDurationBySyscall(OBJECTS,CLOCK_MONOTONIC_COARSE) << " usec\n";
  187. std::cout << "syscall(SYS_clock_gettime, CLOCK_REALTIME_COARSE): " << calcDurationBySyscall(OBJECTS,CLOCK_REALTIME_COARSE) << " usec\n";
  188. std::cout << "\n";
  189. std::cout << "clock_gettime(CLOCK_MONOTONIC): " << calcDurationByGetTime(OBJECTS,CLOCK_MONOTONIC) << " usec\n";
  190. std::cout << "clock_gettime(CLOCK_REALTIME): " << calcDurationByGetTime(OBJECTS,CLOCK_REALTIME) << " usec\n";
  191. std::cout << "clock_gettime(CLOCK_MONOTONIC_RAW): " << calcDurationByGetTime(OBJECTS,CLOCK_MONOTONIC_RAW) << " usec\n";
  192. std::cout << "clock_gettime(CLOCK_MONOTONIC_COARSE): " << calcDurationByGetTime(OBJECTS,CLOCK_MONOTONIC_COARSE) << " usec\n";
  193. std::cout << "clock_gettime(CLOCK_REALTIME_COARSE): " << calcDurationByGetTime(OBJECTS,CLOCK_REALTIME_COARSE) << " usec\n";
  194. std::cout << "\n";
  195. std::cout << "gettimeofday(): " << calcDurationByGetTimeOfDay(OBJECTS) << " usec\n";
  196. return 0;
  197. }