0
0
mirror of https://github.com/yse/easy_profiler.git synced 2024-12-27 08:41:02 +08:00

(Core) #39 Added macros for possibility to choose std::chrono timer type: EASY_CHRONO_HIGHRES_CLOCK for high_resolution_clock and EASY_CHRONO_STEADY_CLOCK for steady_clock - Use it in CMakeLists.txt

This commit is contained in:
Victor Zarubkin 2017-05-04 21:40:48 +03:00
parent 50b3cc8b7a
commit 714e4e0bab
2 changed files with 40 additions and 33 deletions

View File

@ -45,19 +45,38 @@ The Apache License, Version 2.0 (the "License");
#include <easy/profiler.h>
#ifdef _WIN32
#include <Windows.h>
#if defined(_WIN32) && defined(_MSC_VER) && _MSC_VER <= 1800
// std::chrono for MSVC2013 is broken - it has very low resolution of 16ms
// restrict usage of std::chrono
# ifdef EASY_CHRONO_HIGHRES_CLOCK
# undef EASY_CHRONO_HIGHRES_CLOCK
# endif
# ifdef EASY_CHRONO_STEADY_CLOCK
# undef EASY_CHRONO_STEADY_CLOCK
# endif
#endif
#if defined(EASY_CHRONO_HIGHRES_CLOCK)
# include <chrono>
# define EASY_CHRONO_CLOCK std::chrono::high_resolution_clock
#elif defined(EASY_CHRONO_STEADY_CLOCK)
# include <chrono>
# define EASY_CHRONO_CLOCK std::chrono::steady_clock
#elif defined(_WIN32)
# include <Windows.h>
#else
#include <chrono>
#include <time.h>
#ifdef __ARM_ARCH
#include <sys/time.h>
#endif//__ARM_ARCH
# include <chrono>
# include <time.h>
# ifdef __ARM_ARCH
# include <sys/time.h>
# endif//__ARM_ARCH
#endif
static inline profiler::timestamp_t getCurrentTime()
{
#ifdef _WIN32
#if defined(EASY_CHRONO_HIGHRES_CLOCK) || defined(EASY_CHRONO_STEADY_CLOCK)
return (profiler::timestamp_t)EASY_CHRONO_CLOCK::now().time_since_epoch().count();
#elif defined(_WIN32)
//see https://msdn.microsoft.com/library/windows/desktop/dn553408(v=vs.85).aspx
LARGE_INTEGER elapsedMicroseconds;
if (!QueryPerformanceCounter(&elapsedMicroseconds))
@ -138,14 +157,14 @@ static inline profiler::timestamp_t getCurrentTime()
return static_cast<int64_t>(tv.tv_sec) * 1000000 + tv.tv_usec;
#else
#warning You need to define fast getCurrentTime() for your OS and CPU
return std::chrono::time_point_cast<std::chrono::nanoseconds>(std::chrono::system_clock::now()).time_since_epoch().count();
#define USE_STD_CHRONO
return std::chrono::high_resolution_clock::now().time_since_epoch().count();
#define EASY_CHRONO_CLOCK std::chrono::high_resolution_clock
#endif
#else // not _WIN32, __GNUC__, __ICC
#warning You need to define fast getCurrentTime() for your OS and CPU
return std::chrono::time_point_cast<std::chrono::nanoseconds>(std::chrono::system_clock::now()).time_since_epoch().count();
#define USE_STD_CHRONO
return std::chrono::high_resolution_clock::now().time_since_epoch().count();
#define EASY_CHRONO_CLOCK std::chrono::high_resolution_clock
#endif
#endif

View File

@ -147,11 +147,12 @@ extern const uint32_t EASY_CURRENT_VERSION = EASY_VERSION_INT(EASY_PROFILER_VERS
# define MANAGER ProfileManager::instance()
const uint8_t FORCE_ON_FLAG = profiler::FORCE_ON & ~profiler::ON;
#ifdef _WIN32
decltype(LARGE_INTEGER::QuadPart) const CPU_FREQUENCY = ([](){ LARGE_INTEGER freq; QueryPerformanceFrequency(&freq); return freq.QuadPart; })();
#if defined(EASY_CHRONO_CLOCK)
const int64_t CPU_FREQUENCY = EASY_CHRONO_CLOCK::period::den / EASY_CHRONO_CLOCK::period::num;
# define TICKS_TO_US(ticks) ticks * 1000000LL / CPU_FREQUENCY
#elif defined(_WIN32)
const decltype(LARGE_INTEGER::QuadPart) CPU_FREQUENCY = ([](){ LARGE_INTEGER freq; QueryPerformanceFrequency(&freq); return freq.QuadPart; })();
# define TICKS_TO_US(ticks) ticks * 1000000LL / CPU_FREQUENCY
#elif defined(USE_STD_CHRONO)
# define TICKS_TO_US(ticks) ticks / 1000
#else
int64_t calculate_cpu_frequency()
{
@ -255,10 +256,8 @@ extern "C" {
PROFILER_API timestamp_t toNanoseconds(timestamp_t _ticks)
{
#ifdef _WIN32
#if defined(EASY_CHRONO_CLOCK) || defined(_WIN32)
return _ticks * 1000000000LL / CPU_FREQUENCY;
#elif defined(USE_STD_CHRONO)
return _ticks;
#else
return _ticks / CPU_FREQUENCY.load(std::memory_order_acquire);
#endif
@ -266,13 +265,7 @@ extern "C" {
PROFILER_API timestamp_t toMicroseconds(timestamp_t _ticks)
{
#ifdef _WIN32
return _ticks * 1000000LL / CPU_FREQUENCY;
#elif defined(USE_STD_CHRONO)
return _ticks / 1000;
#else
return _ticks * 1000 / CPU_FREQUENCY.load(std::memory_order_acquire);
#endif
return TICKS_TO_US(_ticks);
}
PROFILER_API const BaseBlockDescriptor* registerDescription(EasyBlockStatus _status, const char* _autogenUniqueId, const char* _name, const char* _filename, int _line, block_type_t _block_type, color_t _color, bool _copyName)
@ -740,7 +733,7 @@ ProfileManager::ProfileManager() :
startListen(profiler::DEFAULT_PORT);
#endif
#if !defined(EASY_PROFILER_API_DISABLED) && !defined(_WIN32) && !defined(USE_STD_CHRONO)
#if !defined(EASY_PROFILER_API_DISABLED) && !defined(EASY_CHRONO_CLOCK) && !defined(_WIN32)
const int64_t cpu_frequency = calculate_cpu_frequency();
CPU_FREQUENCY.store(cpu_frequency, std::memory_order_release);
#endif
@ -1453,20 +1446,15 @@ uint32_t ProfileManager::dumpBlocksToStream(profiler::OStream& _outputStream, bo
_outputStream.write(m_processId);
// Write CPU frequency to let GUI calculate real time value from CPU clocks
#ifdef _WIN32
#if defined(EASY_CHRONO_CLOCK) || defined(_WIN32)
_outputStream.write(CPU_FREQUENCY);
#else
#if !defined(USE_STD_CHRONO)
EASY_LOGMSG("Calculating CPU frequency\n");
const int64_t cpu_frequency = calculate_cpu_frequency();
_outputStream.write(cpu_frequency * 1000LL);
EASY_LOGMSG("Done calculating CPU frequency\n");
CPU_FREQUENCY.store(cpu_frequency, std::memory_order_release);
#else
_outputStream.write(0LL);
#endif
#endif
// Write begin and end time