/* * Copyright (c) Meta Platforms, Inc. and affiliates. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. */ /* The contents of this file was borrowed c10/util/ApproximateClock.h */ #pragma once #include #include #include #include #include #include #include namespace libkineto { #if defined(__i386__) || defined(__x86_64__) || defined(__amd64__) #define KINETO_RDTSC #if defined(_MSC_VER) #include #elif defined(__CUDACC__) || defined(__HIPCC__) #undef KINETO_RDTSC #elif defined(__clang__) // `__rdtsc` is available by default. // NB: This has to be first, because Clang will also define `__GNUC__` #elif defined(__GNUC__) #include #else #undef KINETO_RDTSC #endif #endif #if defined(_MSC_VER) && !defined(__clang__) #define KINETO_UNUSED __pragma(warning(suppress : 4100 4101)) #else #define KINETO_UNUSED __attribute__((__unused__)) #endif //_MSC_VER using time_t = int64_t; using steady_clock_t = std::conditional_t< std::chrono::high_resolution_clock::is_steady, std::chrono::high_resolution_clock, std::chrono::steady_clock>; inline time_t getTime(bool allow_monotonic = false) { #if defined(_WIN32) || defined(__MACH__) return std::chrono::duration_cast( steady_clock_t::now().time_since_epoch()) .count(); #else // clock_gettime is *much* faster than std::chrono implementation on Linux struct timespec t {}; auto mode = CLOCK_REALTIME; if (allow_monotonic) { mode = CLOCK_MONOTONIC; } clock_gettime(mode, &t); return static_cast(t.tv_sec) * 1000000000 + static_cast(t.tv_nsec); #endif } // We often do not need to capture true wall times. If a fast mechanism such // as TSC is available we can use that instead and convert back to epoch time // during post processing. This greatly reduce the clock's contribution to // profiling. // http://btorpey.github.io/blog/2014/02/18/clock-sources-in-linux/ // https://quick-bench.com/q/r8opkkGZSJMu9wM_XTbDouq-0Io // TODO: We should use // `https://github.com/google/benchmark/blob/main/src/cycleclock.h` inline auto getApproximateTime() { #if defined(KINETO_RDTSC) return static_cast(__rdtsc()); #else return getTime(); #endif } using approx_time_t = decltype(getApproximateTime()); static_assert( std::is_same_v || std::is_same_v, "Expected either int64_t (`getTime`) or uint64_t (some TSC reads)."); std::function& get_time_converter(); } // namespace libkineto