diff --git a/.travis.yml b/.travis.yml index fb3b109..5d11233 100644 --- a/.travis.yml +++ b/.travis.yml @@ -32,6 +32,7 @@ script: - source /opt/qt55/bin/qt55-env.sh - qmake -v - cmake -DCMAKE_CXX_COMPILER=$CXX_COMPILER -DCMAKE_C_COMPILER=$C_COMPILER .. && make -j3 + - cd sample && $CXX_COMPILER -std=c++11 -O3 main_clock.cpp -o test_clock && ./test_clock before_install: - sudo add-apt-repository --yes ppa:beineri/opt-qt551-trusty - sudo apt-get update -qq diff --git a/sample/main_clock.cpp b/sample/main_clock.cpp new file mode 100644 index 0000000..95fa008 --- /dev/null +++ b/sample/main_clock.cpp @@ -0,0 +1,249 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + + +static inline uint64_t getCurrentTime() +{ +#if defined(__i386__) + int64_t ret; + __asm__ volatile("rdtsc" : "=A"(ret)); + return ret; +#elif defined(__x86_64__) || defined(__amd64__) + uint64_t low, high; + __asm__ volatile("rdtsc" : "=a"(low), "=d"(high)); + return (high << 32) | low; +#endif +} + +int OBJECTS = 500; +#define STR(x) #x + +int64_t calculate_cpu_frequency()//per sec +{ + double g_TicksPerNanoSec; + struct timespec begints, endts; + uint64_t begin = 0, end = 0; + clock_gettime(CLOCK_MONOTONIC, &begints); + begin = getCurrentTime(); + volatile uint64_t i; + for (i = 0; i < 100000000; i++); /* must be CPU intensive */ + end = getCurrentTime(); + clock_gettime(CLOCK_MONOTONIC, &endts); + struct timespec tmpts; + const int NANO_SECONDS_IN_SEC = 1000000000; + tmpts.tv_sec = endts.tv_sec - begints.tv_sec; + tmpts.tv_nsec = endts.tv_nsec - begints.tv_nsec; + if (tmpts.tv_nsec < 0) + { + tmpts.tv_sec--; + tmpts.tv_nsec += NANO_SECONDS_IN_SEC; + } + + uint64_t nsecElapsed = tmpts.tv_sec * 1000000000LL + tmpts.tv_nsec; + g_TicksPerNanoSec = (double)(end - begin) / (double)nsecElapsed; + + int64_t cpu_frequency = int(g_TicksPerNanoSec * 1000); + + return cpu_frequency; +} + +const auto CPU_FREQUENCY = calculate_cpu_frequency(); + +# define TICKS_TO_US(ticks) ticks / CPU_FREQUENCY + +void localSleep(int magic=200000) +{ + volatile int i = 0; + for (; i < magic; ++i); +} + +template +auto calcDelta(int magic=200000) -> decltype(Clock::now().time_since_epoch().count()) +{ + auto start = Clock::now().time_since_epoch().count(); + localSleep(magic); + auto end = Clock::now().time_since_epoch().count(); + return end - start; +} + +template +double calcDuration(int objects) +{ + const auto frequency = Clock::period::den / Clock::period::num; + + auto start = Clock::now(); + + decltype(Clock::now().time_since_epoch().count()) summ = 0; + + for (int i=0; i < objects; i++) + { + summ += calcDelta(); + } + + summ = summ * 1000000LL / frequency; + + auto end = Clock::now(); + auto elapsed = + std::chrono::duration_cast(end - start); + + + return (elapsed.count()-summ)/double(objects)/2.0; +} + +uint64_t calcDeltaRdtsc(int magic=200000) +{ + auto start = getCurrentTime(); + localSleep(magic); + auto end = getCurrentTime(); + return end - start; +} + +double calcDurationByRdtsc(int objects) +{ + auto start = getCurrentTime(); + + uint64_t summ = 0; + + for (int i=0; i < objects; i++) + { + summ += calcDeltaRdtsc(); + } + + auto end = getCurrentTime(); + return TICKS_TO_US((end - start - summ))/double(objects)/2.0; +} + +uint64_t calcDeltaSysCall(int magic, int type) +{ + timespec tp0,tp1; + syscall(SYS_clock_gettime, type, &tp0); + auto start = tp0.tv_sec*1000000000+tp0.tv_nsec; + localSleep(magic); + syscall(SYS_clock_gettime, type, &tp1); + auto end = tp1.tv_sec*1000000000+tp1.tv_nsec; + return end - start; +} + +double calcDurationBySyscall(int objects, int type) +{ + timespec tp0,tp1; + syscall(SYS_clock_gettime, type, &tp0); + auto start = tp0.tv_sec*1000000000+tp0.tv_nsec; + + uint64_t summ = 0; + + for (int i=0; i < objects; i++) + { + summ += calcDeltaSysCall(200000,type); + } + + syscall(SYS_clock_gettime, type, &tp1); + auto end = tp1.tv_sec*1000000000+tp1.tv_nsec; + return (end - start - summ)/double(objects)/2.0/1000.0; +} + +uint64_t calcDeltaSysGetTime(int magic, int type) +{ + timespec tp0,tp1; + clock_gettime(type, &tp0); + auto start = tp0.tv_sec*1000000000+tp0.tv_nsec; + localSleep(magic); + clock_gettime(type, &tp1); + auto end = tp1.tv_sec*1000000000+tp1.tv_nsec; + return end - start; +} + +double calcDurationByGetTime(int objects, int type) +{ + timespec tp0,tp1; + clock_gettime(type, &tp0); + auto start = tp0.tv_sec*1000000000+tp0.tv_nsec; + + uint64_t summ = 0; + + for (int i=0; i < objects; i++) + { + summ += calcDeltaSysGetTime(200000,type); + } + + clock_gettime(type, &tp1); + auto end = tp1.tv_sec*1000000000+tp1.tv_nsec; + return (end - start - summ)/double(objects)/2.0/1000.0; +} + +uint64_t calcDeltaSysGetTimeOfDay(int magic=200000) +{ + timeval tv0,tv1; + gettimeofday(&tv0,0); + auto start = tv0.tv_sec*1000000+tv0.tv_usec; + localSleep(magic); + gettimeofday(&tv1, 0); + auto end = tv1.tv_sec*1000000+tv1.tv_usec; + return end - start; +} + +double calcDurationByGetTimeOfDay(int objects) +{ + timeval tv0,tv1; + gettimeofday(&tv0,0); + auto start = tv0.tv_sec*1000000+tv0.tv_usec; + + uint64_t summ = 0; + + for (int i=0; i < objects; i++) + { + summ += calcDeltaSysGetTimeOfDay(); + } + + gettimeofday(&tv1, 0); + auto end = tv1.tv_sec*1000000+tv1.tv_usec; + return (end - start - summ)/double(objects)/2.0; +} + +int main(int argc, char* argv[]) +{ + if (argc > 1 && argv[1]){ + OBJECTS = std::atoi(argv[1]); + } + + + std::cout << STR(std::chrono::steady_clock) << ": "<(OBJECTS) << " usec\n"; + std::cout << STR(std::chrono::high_resolution_clock)<< ": " << calcDuration(OBJECTS) << " usec\n"; + std::cout << STR(std::chrono::system_clock)<< ": " << calcDuration(OBJECTS) << " usec\n"; + + std::cout << "\n"; + + std::cout << "rdtsc: " << calcDurationByRdtsc(OBJECTS) << " usec\n"; + + std::cout << "\n"; + + std::cout << "syscall(SYS_clock_gettime, CLOCK_MONOTONIC): " << calcDurationBySyscall(OBJECTS,CLOCK_MONOTONIC) << " usec\n"; + std::cout << "syscall(SYS_clock_gettime, CLOCK_REALTIME): " << calcDurationBySyscall(OBJECTS,CLOCK_REALTIME) << " usec\n"; + std::cout << "syscall(SYS_clock_gettime, CLOCK_MONOTONIC_RAW): " << calcDurationBySyscall(OBJECTS,CLOCK_MONOTONIC_RAW) << " usec\n"; + std::cout << "syscall(SYS_clock_gettime, CLOCK_MONOTONIC_COARSE): " << calcDurationBySyscall(OBJECTS,CLOCK_MONOTONIC_COARSE) << " usec\n"; + std::cout << "syscall(SYS_clock_gettime, CLOCK_REALTIME_COARSE): " << calcDurationBySyscall(OBJECTS,CLOCK_REALTIME_COARSE) << " usec\n"; + + std::cout << "\n"; + + std::cout << "clock_gettime(CLOCK_MONOTONIC): " << calcDurationByGetTime(OBJECTS,CLOCK_MONOTONIC) << " usec\n"; + std::cout << "clock_gettime(CLOCK_REALTIME): " << calcDurationByGetTime(OBJECTS,CLOCK_REALTIME) << " usec\n"; + std::cout << "clock_gettime(CLOCK_MONOTONIC_RAW): " << calcDurationByGetTime(OBJECTS,CLOCK_MONOTONIC_RAW) << " usec\n"; + std::cout << "clock_gettime(CLOCK_MONOTONIC_COARSE): " << calcDurationByGetTime(OBJECTS,CLOCK_MONOTONIC_COARSE) << " usec\n"; + std::cout << "clock_gettime(CLOCK_REALTIME_COARSE): " << calcDurationByGetTime(OBJECTS,CLOCK_REALTIME_COARSE) << " usec\n"; + + std::cout << "\n"; + + std::cout << "gettimeofday(): " << calcDurationByGetTimeOfDay(OBJECTS) << " usec\n"; + + return 0; +}