#ifndef LIB_DBG_PERFCOUNTER_MACROS_MQH_INCLUDED #define LIB_DBG_PERFCOUNTER_MACROS_MQH_INCLUDED #property version "5.10" /********************************************************************************** * Copyright (C) 2020 Dominik Egert * * This file is the performance cuonter main user macros include file. * * Lisence applied: GPLv2 * https://www.gnu.org/licenses/old-licenses/gpl-2.0.html * * Author Dominik Egert / Freie Netze UG. ********************************************************************************** * * Version: 5.10 * State: public * * File information * ================ * * * */ //*********************************************************************************************************************************************************/ // // BEGIN Performance profiling support #ifdef LIB_PERF_PROFILING // Output formatting macro #define PERF_PROFILING_OUTPUT_PREFIX(_fl, _fnc, _ln, _fid) StringFormat(">>>perf_profiling<<< >%s< %s(){ @%i:%-25s=> ", _fl, _fnc, _ln, ((_fid == "") || (_fid == NULL) ? " " : " [" + _fid + "] ")) #define PERF_PROFILING_OUTPUT_RESULTS(ex_tm, cnt, avg, min, max) StringFormat("Runtime: %llu micros; %s }", ex_tm, (cnt < 2) ? "" : PERF_PROFILING_OUTPUT_DETAILS(avg, min, max, cnt)) #define PERF_PROFILING_OUTPUT_DETAILS(avg, min, max, cnt) StringFormat("average(%llu), min(%llu), max(%llu); total calls: %i", avg, min, max, cnt) // Output helper macros #define PERF_COUNTER_GET_AVERAGE(x) (LIB_DBG_NAMESPACE(lib_perf, perf_array)[(int)_perf_id_##x] / _perf_calls_##x) #define PERF_COUNTER_GET_MIN(x) LIB_DBG_NAMESPACE(lib_perf, perf_min)[(int)_perf_id_##x] #define PERF_COUNTER_GET_MAX(x) LIB_DBG_NAMESPACE(lib_perf, perf_max)[(int)_perf_id_##x] // Performance output format string #define PERF_OUTPUT_FORMAT_ID(id, x) LIB_DBG_NAMESPACE(lib_perf, perf_print_details)(_perf_runtime_##id, PERF_COUNTER_GET_AVERAGE(id), PERF_COUNTER_GET_MIN(id), PERF_COUNTER_GET_MAX(id), _perf_calls_##id, PERF_PROFILING_OUTPUT_PREFIX(__FILE__, __FUNCTION__, __LINE__, x)) // Performance arrays #define PERF_SET_ARRAYS ((ulong)((ArrayResize(LIB_DBG_NAMESPACE(lib_perf, perf_array), (int)LIB_DBG_NAMESPACE(lib_perf, perf_counters), 512) > NULL) && (ArrayResize(LIB_DBG_NAMESPACE(lib_perf, perf_min), (int)LIB_DBG_NAMESPACE(lib_perf, perf_counters), 512) > NULL) && ((LIB_DBG_NAMESPACE(lib_perf, perf_min)[(int)LIB_DBG_NAMESPACE(lib_perf, perf_counters) - 1] = ULONG_MAX) > 0x00) && (ArrayResize(LIB_DBG_NAMESPACE(lib_perf, perf_max), (int)LIB_DBG_NAMESPACE(lib_perf, perf_counters), 512) > 0x00) && ((LIB_DBG_NAMESPACE(lib_perf, perf_max)[(int)LIB_DBG_NAMESPACE(lib_perf, perf_counters) - 1] = 0x00) == 0x00))) #define PERF_UPDATE_COUNTERS(x) LIB_DBG_NAMESPACE(lib_perf, perf_array)[(int)_perf_id_##x] += _perf_runtime_##x; LIB_DBG_NAMESPACE(lib_perf, perf_min)[(int)_perf_id_##x] = (((LIB_DBG_NAMESPACE(lib_perf, perf_min)[(int)_perf_id_##x] > _perf_runtime_##x) || (LIB_DBG_NAMESPACE(lib_perf, perf_min)[(int)_perf_id_##x] == 0x00)) ? _perf_runtime_##x : LIB_DBG_NAMESPACE(lib_perf, perf_min)[(int)_perf_id_##x]); LIB_DBG_NAMESPACE(lib_perf, perf_max)[(int)_perf_id_##x] = ((LIB_DBG_NAMESPACE(lib_perf, perf_max)[(int)_perf_id_##x] < _perf_runtime_##x) ? _perf_runtime_##x : LIB_DBG_NAMESPACE(lib_perf, perf_max)[(int)_perf_id_##x]); // Counter init #define PERF_COUNTER_DEFINE_ID(x) const static ulong _perf_id_##x = LIB_DBG_NAMESPACE(lib_perf, perf_counters)++; static ulong _perf_start_##x = PERF_SET_ARRAYS; static ulong _perf_calls_##x = (LIB_DBG_NAMESPACE(lib_perf, perf_array)[(int)_perf_id_##x] = 0x00); // Counter start #define PERF_COUNTER_SET_ID(x) _perf_calls_##x++; _perf_start_##x = GetMicrosecondCount(); // Display performance counter #define PERF_COUNTER_CLOSE_ID(id, x) { const ulong _perf_runtime_##id = (GetMicrosecondCount() - _perf_start_##id); PERF_UPDATE_COUNTERS(id); PERF_OUTPUT_FORMAT_ID(id, x); } #define PERF_COUNTER_CLOSE(x) { const ulong _perf_runtime_##x = (GetMicrosecondCount() - _perf_start_##x); PERF_UPDATE_COUNTERS(x); PERF_OUTPUT_FORMAT_ID(x, " {...}; "); } // Predefined function global performance counter macros #define PERF_COUNTER_BEGIN PERF_COUNTER_DEFINE_ID(__FUNCTION__) PERF_COUNTER_SET_ID(__FUNCTION__) #define PERF_COUNTER_END PERF_COUNTER_CLOSE(__FUNCTION__) #define PERF_COUNTER_BEGIN_ID(x) PERF_COUNTER_SET_ID(x) #define PERF_COUNTER_END_ID(x) PERF_COUNTER_CLOSE_ID(x, #x) // Predefined standalone performance measurements #define PERF_COUNTER_TIMEIT_V(x) do { PERF_COUNTER_DEFINE_ID(__LINE__); PERF_COUNTER_BEGIN_ID(__LINE__); x; PERF_COUNTER_CLOSE_ID(__LINE__, #x); } while(false) #ifdef __MQL5__ #define PERF_COUNTER_TIMEIT_R(x) LIB_DBG_NAMESPACE(lib_perf, perf_R_call)(GetMicrosecondCount(), (x), GetMicrosecondCount(), __COUNTER__, #x, __FILE__, __FUNCTION__, __LINE__) #define PERF_COUNTER_TIMEIT_O(x) LIB_DBG_NAMESPACE(lib_perf, perf_O_call)(GetMicrosecondCount(), (x), GetMicrosecondCount(), __COUNTER__, #x, __FILE__, __FUNCTION__, __LINE__) #else #define PERF_COUNTER_TIMEIT_R(x) LIB_DBG_NAMESPACE(lib_perf, perf_R_call)(GetMicrosecondCount(), (x), GetMicrosecondCount(), -1, #x, __FILE__, __FUNCTION__, __LINE__) #define PERF_COUNTER_TIMEIT_O(x) LIB_DBG_NAMESPACE(lib_perf, perf_O_call)(GetMicrosecondCount(), (x), GetMicrosecondCount(), -1, #x, __FILE__, __FUNCTION__, __LINE__) #endif #endif // // END Debugging support //*********************************************************************************************************************************************************/ #endif // LIB_DEBUG_MQH_INCLUDED