diff --git a/common/rfb/util.cxx b/common/rfb/util.cxx index 5a21962..b10d56f 100644 --- a/common/rfb/util.cxx +++ b/common/rfb/util.cxx @@ -550,28 +550,57 @@ namespace rfb { return buffer; } - unsigned msBetween(const struct timeval *first, - const struct timeval *second) + template + unsigned msBetween(const T *first, const T *second) { - unsigned diff; + unsigned diff = (second->tv_sec - first->tv_sec) * 1000; - diff = (second->tv_sec - first->tv_sec) * 1000; + if constexpr (std::is_same_v) { + diff += second->tv_usec / 1000; + diff -= first->tv_usec / 1000; + } else { + diff += (second->tv_nsec - first->tv_nsec) / 1000000; + } - diff += second->tv_usec / 1000; - diff -= first->tv_usec / 1000; - - return diff; + return diff; } - unsigned msSince(const struct timeval *then) - { - struct timeval now; + template + uint64_t usBetween(const T *first, const T *second) { + int64_t diff = (second->tv_sec - first->tv_sec) * 1000000; - gettimeofday(&now, NULL); + if constexpr (std::is_same_v) { + diff += second->tv_usec - first->tv_usec; + } else { + diff += (second->tv_nsec - first->tv_nsec) / 1000; + } + + return diff; + } + + template + unsigned msSince(const T *then) + { + T now; + if constexpr (std::is_same_v) + gettimeofday(&now, NULL); + else + clock_gettime(CLOCK_MONOTONIC, &now); return msBetween(then, &now); } + template + uint64_t usSince(const T *then) { + T now; + if constexpr (std::is_same_v) + gettimeofday(&now, nullptr); + else + clock_gettime(CLOCK_MONOTONIC, &now); + + return usBetween(then, &now); + } + uint64_t elapsedMs(std::chrono::high_resolution_clock::time_point start) { return std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - start).count(); @@ -682,5 +711,15 @@ namespace rfb { usersList = "{\"users\": " + usersList + "} "; return usersList; } + + template unsigned msBetween(const timeval *first, const timeval *second); + template unsigned msBetween(const timespec *first, const timespec *second); + template uint64_t usBetween(const timeval *first, const timeval *second); + template uint64_t usBetween(const timespec *first, const timespec *second); + + template unsigned msSince(const timeval *then); + template unsigned msSince(const timespec *then); + template uint64_t usSince(const timeval *then); + template uint64_t usSince(const timespec *then); }; diff --git a/common/rfb/util.h b/common/rfb/util.h index 9687da9..92f6b30 100644 --- a/common/rfb/util.h +++ b/common/rfb/util.h @@ -134,12 +134,26 @@ namespace rfb { return (secs < 0 || secs > (INT_MAX/1000) ? INT_MAX : secs * 1000); } - // Returns time elapsed between two moments in milliseconds. - unsigned msBetween(const struct timeval *first, - const struct timeval *second); + template + concept TimeType = std::is_same_v || std::is_same_v; - // Returns time elapsed since given moment in milliseconds. - unsigned msSince(const struct timeval *then); + // Returns time elapsed between two moments in milliseconds. + template + unsigned msBetween(const T *first, + const T *second); + + // Returns time elapsed between two moments in microseconds. + template + uint64_t usBetween(const T *first, + const T *second); + + // Returns time elapsed since the given moment in milliseconds. + template + unsigned msSince(const T *then); + + // Returns time elapsed since the given moment in microseconds + template + uint64_t usSince(const T *then); /** * Calculates the number of milliseconds elapsed since a given starting point. @@ -176,4 +190,61 @@ namespace rfb { #define __rfbmin(a,b) (((a) < (b)) ? (a) : (b)) #endif +#define STOPWATCH_END_US(name, result) \ + const auto result = usSince(&name) + +#define STOPWATCH_END_MS(name, result) \ + const auto result = msSince(&name) + +#define STOPWATCH_PRINT_US(log, name) \ + STOPWATCH_END_US(name, name##_end); \ + log.debug("Time "#name": %lu us", name##_end) + +#define STOPWATCH_PRINT_MS(log, name) \ + STOPWATCH_END_MS(name, name##_end); \ + log.debug("Time "#name": %u ms", name##_end) + +#define COARSE_STOPWATCH(name) \ + timespec name; \ + clock_gettime(CLOCK_MONOTONIC_COARSE, &name) + +#define COARSE_STOPWATCH_PRINT_MS(log, name) STOPWATCH_PRINT_MS(log, name) + +#define MONOTONIC_STOPWATCH(name) \ + timespec name; \ + clock_gettime(CLOCK_MONOTONIC, &name) + +#define MONOTONIC_STOPWATCH_PRINT_US(log, name) STOPWATCH_PRINT_US(log, name) + +#define MONOTONIC_STOPWATCH_PRINT_MS(log, name) STOPWATCH_PRINT_MS(log, name) + +#define TIMEOFDAY_STOPWATCH(name) \ + timeval name; \ + gettimeofday(&name, nullptr) + +#define TIMEOFDAY_STOPWATCH_PRINT_MS(log, name) STOPWATCH_PRINT_MS(log, name) + +#define TRACE_STOPWATCH(name) COARSE_STOPWATCH(name) + +#define TRACE_STOPWATCH_PRINT_MS(log, name) COARSE_STOPWATCH_PRINT_MS(log, name) + +#define TRACE_STOPWATCH_END_MS(name, result) STOPWATCH_END_MS(name, result) + +#ifndef NDEBUG +#define DEBUG_STOPWATCH(name) MONOTONIC_STOPWATCH(name) +#else +#define DEBUG_STOPWATCH(name) #endif + +#ifndef NDEBUG +#define DEBUG_STOPWATCH_PRINT_US(log, name) MONOTONIC_STOPWATCH_PRINT_US(log, name) + +#define DEBUG_STOPWATCH_PRINT_MS(log, name) MONOTONIC_STOPWATCH_PRINT_MS(log, name) +#else +#define DEBUG_STOPWATCH_PRINT_US(log, name) + +#define DEBUG_STOPWATCH_PRINT_MS(log, name) +#endif + +#endif +