From: Joel Rosdahl Date: Wed, 21 Feb 2024 20:20:58 +0000 (+0100) Subject: chore: Remove internal tracing framework X-Git-Tag: v4.10~82 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1dc07d392a9700bca2e6b93198ec2b2d4627fb7d;p=thirdparty%2Fccache.git chore: Remove internal tracing framework The internal tracing calls enabled by ENABLE_TRACING work fine, but I have found that I never use them or add tracepoints to new code, so in reality they mostly contribute with dead weight. In an effort to reduce the amount of dependencies, I have therefore decided to remove the trace calls, including the bundled minitrace sources. --- diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index f466e1eb..990e6a13 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -258,13 +258,13 @@ jobs: fail-fast: false matrix: include: - - name: Linux GCC debug + in source + tracing + - name: Linux GCC debug + in source os: ubuntu-20.04 CC: gcc CXX: g++ BUILDDIR: . CCACHE_LOC: . - CMAKE_PARAMS: -DCMAKE_BUILD_TYPE=Debug -DENABLE_TRACING=1 + CMAKE_PARAMS: -DCMAKE_BUILD_TYPE=Debug apt_get: elfutils libzstd-dev pkg-config libhiredis-dev - name: Linux GCC 32-bit diff --git a/CMakeLists.txt b/CMakeLists.txt index 381d3e72..5f0dd388 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -117,7 +117,6 @@ endif() # doesn't get scanned. # include(CodeAnalysis) -option(ENABLE_TRACING "Enable possibility to use internal ccache tracing" OFF) # # Source code diff --git a/LICENSE.adoc b/LICENSE.adoc index 981db455..bf5ad93a 100644 --- a/LICENSE.adoc +++ b/LICENSE.adoc @@ -522,36 +522,6 @@ SOFTWARE. ---- -=== src/third_party/minitrace.* - -A library for producing JSON traces suitable for Chrome's built-in trace viewer -(chrome://tracing). Downloaded from . - ----- -The MIT License (MIT) - -Copyright (c) 2014 Henrik Rydgård - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----- - - === src/third_party/nonstd/span.hpp This is the single header version of diff --git a/cmake/GenerateConfigurationFile.cmake b/cmake/GenerateConfigurationFile.cmake index 60c18053..ffb2ddef 100644 --- a/cmake/GenerateConfigurationFile.cmake +++ b/cmake/GenerateConfigurationFile.cmake @@ -89,9 +89,6 @@ if(CMAKE_SYSTEM MATCHES "Darwin") set(_DARWIN_C_SOURCE 1) endif() -# alias -set(MTR_ENABLED "${ENABLE_TRACING}") - if(HAVE_SYS_MMAN_H AND (HAVE_STRUCT_STAT_ST_MTIM OR HAVE_STRUCT_STAT_ST_MTIMESPEC) AND (HAVE_LINUX_FS_H OR HAVE_STRUCT_STATFS_F_FSTYPENAME)) diff --git a/cmake/config.h.in b/cmake/config.h.in index 08e9ad9a..b1cf34e8 100644 --- a/cmake/config.h.in +++ b/cmake/config.h.in @@ -67,8 +67,6 @@ # pragma clang diagnostic pop #endif -#cmakedefine MTR_ENABLED - // === Header files === // Define if you have the header file. diff --git a/doc/DEVELOPER.md b/doc/DEVELOPER.md deleted file mode 100644 index e211c9ff..00000000 --- a/doc/DEVELOPER.md +++ /dev/null @@ -1,33 +0,0 @@ -Developer manual -================ - -Tracing -------- - -In order to see what ccache is doing, it is possible to enable internal -tracing: - -* Build ccache with the `-DENABLE_TRACING=1` cmake option. -* Set the environment variable `CCACHE_INTERNAL_TRACE` to instruct ccache to - create trace files at runtime. - -There will be one trace file per ccache invocation, named as the object file -with a `.ccache-trace` suffix, e.g. `file.o.ccache-trace`. The trace file can -then be loaded into the `chrome://tracing` page of Chromium/Chrome. - -You can combine several trace files into by using the `misc/combine-trace-files` -script: - - misc/combine-trace-files *.o.ccache-trace | gzip > ccache.trace.gz - -(The gzip step is optional; Chrome supports both plain trace files and gzipped -trace files.) The script will offset each individual trace by its start time in -the combined file. - -There is also a script called `summarize-trace-files` that generates a summary -(per job slot) of all the ccache runs: - - misc/combine-trace-files *.o.ccache-trace | misc/summarize-trace-files 4 > ccache.trace - -The script takes the number of job slots you used when building (e.g. `4` for -`make -j4`) as the first argument. diff --git a/misc/combine-trace-files b/misc/combine-trace-files deleted file mode 100755 index a581270e..00000000 --- a/misc/combine-trace-files +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/env python3 - -import json -import sys - -traces = {} -for arg in sys.argv[1:]: - events = json.load(open(arg))["traceEvents"] - for event in events: - if event["name"] == "" and event["ph"] == "I": - time = float(event["args"]["time"]) - # print "%.6f" % time - traces[time] = events - break - -times = sorted(traces) -min_time = min(times) - -combined_events = [] -for time in times: - offset = (time - min_time) * 1000000.0 - events = traces[time] - for event in events: - event["ts"] = int(event["ts"] + offset) - combined_events.append(event) - -print(json.dumps({"traceEvents": combined_events})) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 68b64657..3b85874f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -20,10 +20,6 @@ if(INODE_CACHE_SUPPORTED) list(APPEND source_files InodeCache.cpp) endif() -if(MTR_ENABLED) - list(APPEND source_files MiniTrace.cpp) -endif() - if(NOT WIN32) list(APPEND source_files SignalHandler.cpp) endif() diff --git a/src/Config.cpp b/src/Config.cpp index 328e962d..1440dc86 100644 --- a/src/Config.cpp +++ b/src/Config.cpp @@ -18,7 +18,6 @@ #include "Config.hpp" -#include "MiniTrace.hpp" #include "Util.hpp" #include @@ -573,10 +572,8 @@ Config::read(const std::vector& cmdline_config_settings) set_system_config_path(env_ccache_configpath2 ? env_ccache_configpath2 : Util::make_path(sysconfdir, "ccache.conf")); - MTR_BEGIN("config", "conf_read_system"); // A missing config file in SYSCONFDIR is OK so don't check return value. update_from_file(system_config_path()); - MTR_END("config", "conf_read_system"); const char* const env_ccache_dir = getenv("CCACHE_DIR"); auto cmdline_cache_dir = cmdline_settings_map.find("cache_dir"); @@ -618,17 +615,13 @@ Config::read(const std::vector& cmdline_config_settings) const std::string& cache_dir_before_config_file_was_read = cache_dir(); - MTR_BEGIN("config", "conf_read"); update_from_file(config_path()); - MTR_END("config", "conf_read"); // Ignore cache_dir set in configuration file set_cache_dir(cache_dir_before_config_file_was_read); - MTR_BEGIN("config", "conf_update_from_environment"); update_from_environment(); // (cache_dir is set above if CCACHE_DIR is set.) - MTR_END("config", "conf_update_from_environment"); update_from_map(cmdline_settings_map); diff --git a/src/Context.hpp b/src/Context.hpp index bfc31221..98716ae3 100644 --- a/src/Context.hpp +++ b/src/Context.hpp @@ -21,9 +21,6 @@ #include "Args.hpp" #include "ArgsInfo.hpp" #include "Config.hpp" -#ifdef MTR_ENABLED -# include "MiniTrace.hpp" -#endif #include #include @@ -116,11 +113,6 @@ public: // `nullopt` if there is no such configuration. std::optional original_umask; -#ifdef MTR_ENABLED - // Internal tracing. - std::unique_ptr mini_trace; -#endif - // Whether we have added "/showIncludes" ourselves since it's missing and // depend mode is enabled. bool auto_depend_mode = false; diff --git a/src/MiniTrace.cpp b/src/MiniTrace.cpp deleted file mode 100644 index 0850bb91..00000000 --- a/src/MiniTrace.cpp +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright (C) 2020-2023 Joel Rosdahl and other contributors -// -// See doc/AUTHORS.adoc for a complete list of contributors. -// -// This program is free software; you can redistribute it and/or modify it -// under the terms of the GNU General Public License as published by the Free -// Software Foundation; either version 3 of the License, or (at your option) -// any later version. -// -// This program is distributed in the hope that it will be useful, but WITHOUT -// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -// more details. -// -// You should have received a copy of the GNU General Public License along with -// this program; if not, write to the Free Software Foundation, Inc., 51 -// Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -#include "MiniTrace.hpp" - -#include "ArgsInfo.hpp" - -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef HAVE_UNISTD_H -# include -#endif - -namespace fs = util::filesystem; - -MiniTrace::MiniTrace(const ArgsInfo& args_info) - : m_args_info(args_info), - m_trace_id(reinterpret_cast(getpid())) -{ - auto tmp_dir = fs::temp_directory_path(); - if (!tmp_dir) { - tmp_dir = "/tmp"; - } - auto tmp_file = util::value_or_throw( - util::TemporaryFile::create(*tmp_dir / "ccache-trace")); - m_tmp_trace_file = tmp_file.path; - - mtr_init(m_tmp_trace_file.c_str()); - auto now = util::TimePoint::now(); - m_start_time = FMT("{}.{:06}", now.sec(), now.nsec_decimal_part() / 1000); - MTR_INSTANT_C("", "", "time", m_start_time.c_str()); - MTR_META_PROCESS_NAME("ccache"); - MTR_START("program", "ccache", m_trace_id); -} - -MiniTrace::~MiniTrace() -{ - MTR_FINISH("program", "ccache", m_trace_id); - mtr_flush(); - mtr_shutdown(); - - if (!m_args_info.output_obj.empty()) { - util::copy_file(m_tmp_trace_file, m_args_info.output_obj + ".ccache-trace"); - } - util::remove(m_tmp_trace_file); -} diff --git a/src/MiniTrace.hpp b/src/MiniTrace.hpp deleted file mode 100644 index 76aae381..00000000 --- a/src/MiniTrace.hpp +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (C) 2020-2021 Joel Rosdahl and other contributors -// -// See doc/AUTHORS.adoc for a complete list of contributors. -// -// This program is free software; you can redistribute it and/or modify it -// under the terms of the GNU General Public License as published by the Free -// Software Foundation; either version 3 of the License, or (at your option) -// any later version. -// -// This program is distributed in the hope that it will be useful, but WITHOUT -// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -// more details. -// -// You should have received a copy of the GNU General Public License along with -// this program; if not, write to the Free Software Foundation, Inc., 51 -// Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -#pragma once - -#include "third_party/minitrace.h" - -#include - -struct ArgsInfo; - -class MiniTrace -{ -public: - MiniTrace(const ArgsInfo& args_info); - ~MiniTrace(); - -private: - const ArgsInfo& m_args_info; - const void* const m_trace_id; - std::string m_tmp_trace_file; - std::string m_start_time; -}; diff --git a/src/ccache.cpp b/src/ccache.cpp index 3cbe27ea..10b38f1e 100644 --- a/src/ccache.cpp +++ b/src/ccache.cpp @@ -24,7 +24,6 @@ #include "Context.hpp" #include "Depfile.hpp" #include "Hash.hpp" -#include "MiniTrace.hpp" #include "SignalHandler.hpp" #include "Util.hpp" #include "argprocessing.hpp" @@ -809,8 +808,6 @@ update_manifest(Context& ctx, ASSERT(ctx.config.direct_mode()); - MTR_SCOPE("manifest", "manifest_put"); - // ctime() may be 0, so we have to check time_of_invocation against // MAX(mtime, ctime). // @@ -1127,7 +1124,6 @@ to_cache(Context& ctx, } LOG_RAW("Running real compiler"); - MTR_BEGIN("execute", "compiler"); tl::expected result; if (!ctx.config.depend_mode()) { @@ -1145,7 +1141,6 @@ to_cache(Context& ctx, result = do_execute(ctx, depend_mode_args); } - MTR_END("execute", "compiler"); if (!result) { return tl::unexpected(result.error()); @@ -1231,12 +1226,10 @@ to_cache(Context& ctx, } } - MTR_BEGIN("result", "result_put"); if (!write_result( ctx, *result_key, result->stdout_data, result->stderr_data)) { return tl::unexpected(Statistic::compiler_produced_no_output); } - MTR_END("result", "result_put"); // Everything OK. core::send_to_console( @@ -1299,9 +1292,7 @@ get_result_key_from_cpp(Context& ctx, Args& args, Hash& hash) add_prefix(args, ctx.config.prefix_command_cpp()); LOG_RAW("Running preprocessor"); - MTR_BEGIN("execute", "preprocessor"); const auto result = do_execute(ctx, args, false); - MTR_END("execute", "preprocessor"); args.pop_back(args.size() - orig_args_size); if (!result) { @@ -1984,7 +1975,6 @@ hash_profiling_related_data(const Context& ctx, Hash& hash) static std::optional get_result_key_from_manifest(Context& ctx, const Hash::Digest& manifest_key) { - MTR_BEGIN("manifest", "manifest_get"); std::optional result_key; size_t read_manifests = 0; ctx.storage.get( @@ -2004,9 +1994,7 @@ get_result_key_from_manifest(Context& ctx, const Hash::Digest& manifest_key) return false; } }); - MTR_END("manifest", "manifest_get"); if (read_manifests > 1 && !ctx.config.remote_only()) { - MTR_SCOPE("manifest", "merge"); LOG("Storing merged manifest {} locally", util::format_digest(manifest_key)); core::CacheEntry::Header header(ctx.config, core::CacheEntryType::manifest); @@ -2155,8 +2143,6 @@ from_cache(Context& ctx, FromCacheCallMode mode, const Hash::Digest& result_key) return false; } - MTR_SCOPE("cache", "from_cache"); - // Get result from cache. util::Bytes cache_entry_data; ctx.storage.get( @@ -2233,14 +2219,6 @@ initialize(Context& ctx, const char* const* argv, bool masquerading_as_compiler) LOG("Configuration file: {}", ctx.config.config_path()); LOG("System configuration file: {}", ctx.config.system_config_path()); - if (getenv("CCACHE_INTERNAL_TRACE")) { -#ifdef MTR_ENABLED - ctx.mini_trace = std::make_unique(ctx.args_info); -#else - LOG_RAW("Error: tracing is not enabled!"); -#endif - } - if (!ctx.config.log_file().empty() || ctx.config.debug()) { ctx.config.visit_items([&ctx](const std::string& key, const std::string& value, @@ -2262,9 +2240,7 @@ initialize(Context& ctx, const char* const* argv, bool masquerading_as_compiler) ctx.storage.initialize(); - MTR_BEGIN("main", "find_compiler"); find_compiler(ctx, &find_executable, masquerading_as_compiler); - MTR_END("main", "find_compiler"); // Guess compiler after logging the config value in order to be able to // display "compiler_type = auto" before overwriting the value with the @@ -2476,9 +2452,7 @@ do_cache_compilation(Context& ctx) // be disabled. util::setenv("CCACHE_DISABLE", "1"); - MTR_BEGIN("main", "process_args"); ProcessArgsResult processed = process_args(ctx); - MTR_END("main", "process_args"); if (processed.error) { return tl::unexpected(*processed.error); @@ -2553,7 +2527,6 @@ do_cache_compilation(Context& ctx) } LOG("Object file: {}", ctx.args_info.output_obj); - MTR_META_THREAD_NAME(ctx.args_info.output_obj.c_str()); if (ctx.config.debug() && ctx.config.debug_level() >= 2) { const auto path = prepare_debug_path(ctx.apparent_cwd, @@ -2583,11 +2556,8 @@ do_cache_compilation(Context& ctx) return tl::unexpected(Statistic::disabled); } - { - MTR_SCOPE("hash", "common_hash"); - TRY(hash_common_info( - ctx, processed.preprocessor_args, common_hash, ctx.args_info)); - } + TRY(hash_common_info( + ctx, processed.preprocessor_args, common_hash, ctx.args_info)); if (processed.hash_actual_cwd) { common_hash.hash_delimiter("actual_cwd"); @@ -2608,10 +2578,8 @@ do_cache_compilation(Context& ctx) if (ctx.config.direct_mode()) { LOG_RAW("Trying direct lookup"); - MTR_BEGIN("hash", "direct_hash"); const auto result_and_manifest_key = calculate_result_and_manifest_key( ctx, args_to_hash, direct_hash, nullptr); - MTR_END("hash", "direct_hash"); if (!result_and_manifest_key) { return tl::unexpected(result_and_manifest_key.error()); } @@ -2652,10 +2620,8 @@ do_cache_compilation(Context& ctx) Hash cpp_hash = common_hash; init_hash_debug(ctx, cpp_hash, 'p', "PREPROCESSOR MODE", debug_text_file); - MTR_BEGIN("hash", "cpp_hash"); const auto result_and_manifest_key = calculate_result_and_manifest_key( ctx, args_to_hash, cpp_hash, &processed.preprocessor_args); - MTR_END("hash", "cpp_hash"); if (!result_and_manifest_key) { return tl::unexpected(result_and_manifest_key.error()); } @@ -2693,7 +2659,6 @@ do_cache_compilation(Context& ctx) return tl::unexpected(from_cache_result.error()); } else if (*from_cache_result) { if (ctx.config.direct_mode() && manifest_key && put_result_in_manifest) { - MTR_SCOPE("cache", "update_manifest"); update_manifest(ctx, *manifest_key, *result_key); } return Statistic::preprocessed_cache_hit; @@ -2715,20 +2680,17 @@ do_cache_compilation(Context& ctx) Hash* depend_mode_hash = ctx.config.depend_mode() ? &direct_hash : nullptr; // Run real compiler, sending output to cache. - MTR_BEGIN("cache", "to_cache"); const auto digest = to_cache(ctx, processed.compiler_args, result_key, ctx.args_info.depend_extra_args, depend_mode_hash); - MTR_END("cache", "to_cache"); if (!digest) { return tl::unexpected(digest.error()); } result_key = *digest; if (ctx.config.direct_mode()) { ASSERT(manifest_key); - MTR_SCOPE("cache", "update_manifest"); update_manifest(ctx, *manifest_key, *result_key); } diff --git a/src/storage/Storage.cpp b/src/storage/Storage.cpp index 506ff6bc..ddb21b7a 100644 --- a/src/storage/Storage.cpp +++ b/src/storage/Storage.cpp @@ -19,7 +19,6 @@ #include "Storage.hpp" #include -#include #include #include #include @@ -268,8 +267,6 @@ Storage::get(const Hash::Hash::Digest& key, const core::CacheEntryType type, const EntryReceiver& entry_receiver) { - MTR_SCOPE("storage", "get"); - if (!m_config.remote_only()) { auto value = local.get(key, type); if (value) { @@ -295,8 +292,6 @@ Storage::put(const Hash::Digest& key, const core::CacheEntryType type, nonstd::span value) { - MTR_SCOPE("storage", "put"); - if (!m_config.remote_only()) { local.put(key, type, value); } @@ -306,8 +301,6 @@ Storage::put(const Hash::Digest& key, void Storage::remove(const Hash::Digest& key, const core::CacheEntryType type) { - MTR_SCOPE("storage", "remove"); - if (!m_config.remote_only()) { local.remove(key, type); } @@ -464,8 +457,6 @@ Storage::get_from_remote_storage(const Hash::Digest& key, const core::CacheEntryType type, const EntryReceiver& entry_receiver) { - MTR_SCOPE("remote_storage", "get"); - for (const auto& entry : m_remote_storages) { auto backend = get_backend(*entry, key, "getting from", false); if (!backend) { @@ -508,8 +499,6 @@ Storage::put_in_remote_storage(const Hash::Digest& key, nonstd::span value, bool only_if_missing) { - MTR_SCOPE("remote_storage", "put"); - if (!core::CacheEntry::Header(value).self_contained) { LOG("Not putting {} in remote storage since it's not self-contained", util::format_digest(key)); @@ -544,8 +533,6 @@ Storage::put_in_remote_storage(const Hash::Digest& key, void Storage::remove_from_remote_storage(const Hash::Digest& key) { - MTR_SCOPE("remote_storage", "remove"); - for (const auto& entry : m_remote_storages) { auto backend = get_backend(*entry, key, "removing from", true); if (!backend) { diff --git a/src/storage/local/LocalStorage.cpp b/src/storage/local/LocalStorage.cpp index a55e26fa..1a38afed 100644 --- a/src/storage/local/LocalStorage.cpp +++ b/src/storage/local/LocalStorage.cpp @@ -20,7 +20,6 @@ #include #include -#include #include #include #include @@ -492,8 +491,6 @@ LocalStorage::finalize() std::optional LocalStorage::get(const Hash::Digest& key, const core::CacheEntryType type) { - MTR_SCOPE("local_storage", "get"); - std::optional return_value; const auto cache_file = look_up_cache_file(key, type); @@ -530,8 +527,6 @@ LocalStorage::put(const Hash::Digest& key, nonstd::span value, bool only_if_missing) { - MTR_SCOPE("local_storage", "put"); - const auto cache_file = look_up_cache_file(key, type); if (only_if_missing && cache_file.dir_entry.exists()) { LOG("Not storing {} in local storage since it already exists", @@ -595,8 +590,6 @@ LocalStorage::put(const Hash::Digest& key, void LocalStorage::remove(const Hash::Digest& key, const core::CacheEntryType type) { - MTR_SCOPE("local_storage", "remove"); - const auto cache_file = look_up_cache_file(key, type); if (!cache_file.dir_entry) { LOG("No {} to remove from local storage", util::format_digest(key)); @@ -1456,8 +1449,6 @@ LocalStorage::acquire_all_level_2_content_locks( void LocalStorage::clean_internal_tempdir() { - MTR_SCOPE("local_storage", "clean_internal_tempdir"); - const auto now = util::TimePoint::now(); const auto cleaned_stamp = FMT("{}/.cleaned", m_config.temporary_dir()); DirEntry cleaned_dir_entry(cleaned_stamp); diff --git a/src/third_party/CMakeLists.txt b/src/third_party/CMakeLists.txt index 549f51e4..a615dcf6 100644 --- a/src/third_party/CMakeLists.txt +++ b/src/third_party/CMakeLists.txt @@ -10,10 +10,6 @@ if(WIN32) target_sources(third_party PRIVATE win32/mktemp.c) endif () -if(ENABLE_TRACING) - target_sources(third_party PRIVATE minitrace.c) -endif() - file(GLOB headers *.h fmt/*.h nonstd/*.hpp win32/*.h) target_sources(third_party PRIVATE ${headers}) diff --git a/src/third_party/minitrace.c b/src/third_party/minitrace.c deleted file mode 100644 index 2877f048..00000000 --- a/src/third_party/minitrace.c +++ /dev/null @@ -1,484 +0,0 @@ -// minitrace -// Copyright 2014 by Henrik Rydgård -// http://www.github.com/hrydgard/minitrace -// Released under the MIT license. - -// See minitrace.h for basic documentation. - -#include -#include -#include - -#ifdef _WIN32 -#pragma warning (disable:4996) -#define WIN32_LEAN_AND_MEAN -#include -#define __thread __declspec(thread) -#define pthread_mutex_t CRITICAL_SECTION -#define pthread_mutex_init(a, b) InitializeCriticalSection(a) -#define pthread_mutex_lock(a) EnterCriticalSection(a) -#define pthread_mutex_unlock(a) LeaveCriticalSection(a) -#define pthread_mutex_destroy(a) DeleteCriticalSection(a) -#else -#include -#include -#include -#include -#endif - -#include "minitrace.h" - -#ifdef __GNUC__ -#define ATTR_NORETURN __attribute__((noreturn)) -#else -#define ATTR_NORETURN -#endif - -#define ARRAY_SIZE(x) sizeof(x)/sizeof(x[0]) -#define TRUE 1 -#define FALSE 0 - -// Ugh, this struct is already pretty heavy. -// Will probably need to move arguments to a second buffer to support more than one. -typedef struct raw_event { - const char *name; - const char *cat; - void *id; - int64_t ts; - uint32_t pid; - uint32_t tid; - char ph; - mtr_arg_type arg_type; - const char *arg_name; - union { - const char *a_str; - int a_int; - double a_double; - }; -} raw_event_t; - -static raw_event_t *event_buffer; -static raw_event_t *flush_buffer; -static volatile int event_count; -static int is_tracing = FALSE; -static int is_flushing = FALSE; -static int events_in_progress = 0; -static int64_t time_offset; -static int first_line = 1; -static FILE *f; -static __thread int cur_thread_id; // Thread local storage -static int cur_process_id; -static pthread_mutex_t mutex; -static pthread_mutex_t event_mutex; - -#define STRING_POOL_SIZE 100 -static char *str_pool[100]; - -// forward declaration -void mtr_flush_with_state(int); - -// Tiny portability layer. -// Exposes: -// get_cur_thread_id() -// get_cur_process_id() -// mtr_time_s() -// pthread basics -#ifdef _WIN32 -static int get_cur_thread_id() { - return (int)GetCurrentThreadId(); -} -static int get_cur_process_id() { - return (int)GetCurrentProcessId(); -} - -static uint64_t _frequency = 0; -static uint64_t _starttime = 0; -double mtr_time_s() { - if (_frequency == 0) { - QueryPerformanceFrequency((LARGE_INTEGER*)&_frequency); - QueryPerformanceCounter((LARGE_INTEGER*)&_starttime); - } - __int64 time; - QueryPerformanceCounter((LARGE_INTEGER*)&time); - return ((double) (time - _starttime) / (double) _frequency); -} - -// Ctrl+C handling for Windows console apps -static BOOL WINAPI CtrlHandler(DWORD fdwCtrlType) { - if (is_tracing && fdwCtrlType == CTRL_C_EVENT) { - printf("Ctrl-C detected! Flushing trace and shutting down.\n\n"); - mtr_flush(); - mtr_shutdown(); - } - ExitProcess(1); -} - -void mtr_register_sigint_handler() { - // For console apps: - SetConsoleCtrlHandler(&CtrlHandler, TRUE); -} - -#else - -static inline int get_cur_thread_id() { - return (int)(intptr_t)pthread_self(); -} -static inline int get_cur_process_id() { - return (int)getpid(); -} - -#if defined(BLACKBERRY) -double mtr_time_s() { - struct timespec time; - clock_gettime(CLOCK_MONOTONIC, &time); // Linux must use CLOCK_MONOTONIC_RAW due to time warps - return time.tv_sec + time.tv_nsec / 1.0e9; -} -#else -double mtr_time_s() { - static time_t start; - struct timeval tv; - gettimeofday(&tv, NULL); - if (start == 0) { - start = tv.tv_sec; - } - tv.tv_sec -= start; - return (double)tv.tv_sec + (double)tv.tv_usec / 1000000.0; -} -#endif // !BLACKBERRY - -static void termination_handler(int signum) ATTR_NORETURN; -static void termination_handler(int signum) { - (void) signum; - if (is_tracing) { - printf("Ctrl-C detected! Flushing trace and shutting down.\n\n"); - mtr_flush(); - fwrite("\n]}\n", 1, 4, f); - fclose(f); - } - exit(1); -} - -void mtr_register_sigint_handler() { -#ifndef MTR_ENABLED - return; -#endif - // Avoid altering set-to-be-ignored handlers while registering. - if (signal(SIGINT, &termination_handler) == SIG_IGN) - signal(SIGINT, SIG_IGN); -} - -#endif - -void mtr_init_from_stream(void *stream) { -#ifndef MTR_ENABLED - return; -#endif - event_buffer = (raw_event_t *)malloc(INTERNAL_MINITRACE_BUFFER_SIZE * sizeof(raw_event_t)); - flush_buffer = (raw_event_t *)malloc(INTERNAL_MINITRACE_BUFFER_SIZE * sizeof(raw_event_t)); - is_tracing = 1; - event_count = 0; - f = (FILE *)stream; - const char *header = "{\"traceEvents\":[\n"; - fwrite(header, 1, strlen(header), f); - time_offset = (uint64_t)(mtr_time_s() * 1000000); - first_line = 1; - pthread_mutex_init(&mutex, 0); - pthread_mutex_init(&event_mutex, 0); -} - -void mtr_init(const char *json_file) { -#ifndef MTR_ENABLED - return; -#endif - mtr_init_from_stream(fopen(json_file, "wb")); -} - -void mtr_shutdown() { - int i; -#ifndef MTR_ENABLED - return; -#endif - pthread_mutex_lock(&mutex); - is_tracing = FALSE; - pthread_mutex_unlock(&mutex); - mtr_flush_with_state(TRUE); - - fwrite("\n]}\n", 1, 4, f); - fclose(f); - pthread_mutex_destroy(&mutex); - pthread_mutex_destroy(&event_mutex); - f = 0; - free(event_buffer); - event_buffer = 0; - for (i = 0; i < STRING_POOL_SIZE; i++) { - if (str_pool[i]) { - free(str_pool[i]); - str_pool[i] = 0; - } - } -} - -const char *mtr_pool_string(const char *str) { - int i; - for (i = 0; i < STRING_POOL_SIZE; i++) { - if (!str_pool[i]) { - str_pool[i] = (char*)malloc(strlen(str) + 1); - strcpy(str_pool[i], str); - return str_pool[i]; - } else { - if (!strcmp(str, str_pool[i])) - return str_pool[i]; - } - } - return "string pool full"; -} - -void mtr_start() { -#ifndef MTR_ENABLED - return; -#endif - pthread_mutex_lock(&mutex); - is_tracing = TRUE; - pthread_mutex_unlock(&mutex); -} - -void mtr_stop() { -#ifndef MTR_ENABLED - return; -#endif - pthread_mutex_lock(&mutex); - is_tracing = FALSE; - pthread_mutex_unlock(&mutex); -} - -// TODO: fwrite more than one line at a time. -// Flushing is thread safe and process async -// using double-buffering mechanism. -// Aware: only one flushing process may be -// running at any point of time -void mtr_flush_with_state(int is_last) { -#ifndef MTR_ENABLED - return; -#endif - int i = 0; - char linebuf[1024]; - char arg_buf[1024]; - char id_buf[256]; - int event_count_copy = 0; - int events_in_progress_copy = 1; - raw_event_t *event_buffer_tmp = NULL; - - // small critical section to swap buffers - // - no any new events can be spawn while - // swapping since they tied to the same mutex - // - checks for any flushing in process - pthread_mutex_lock(&mutex); - // if not flushing already - if (is_flushing) { - pthread_mutex_unlock(&mutex); - return; - } - is_flushing = TRUE; - event_count_copy = event_count; - event_buffer_tmp = flush_buffer; - flush_buffer = event_buffer; - event_buffer = event_buffer_tmp; - event_count = 0; - // waiting for any unfinished events before swap - while (events_in_progress_copy != 0) { - pthread_mutex_lock(&event_mutex); - events_in_progress_copy = events_in_progress; - pthread_mutex_unlock(&event_mutex); - } - pthread_mutex_unlock(&mutex); - - for (i = 0; i < event_count_copy; i++) { - raw_event_t *raw = &flush_buffer[i]; - int len; - switch (raw->arg_type) { - case MTR_ARG_TYPE_INT: - snprintf(arg_buf, ARRAY_SIZE(arg_buf), "\"%s\":%i", raw->arg_name, raw->a_int); - break; - case MTR_ARG_TYPE_STRING_CONST: - snprintf(arg_buf, ARRAY_SIZE(arg_buf), "\"%s\":\"%s\"", raw->arg_name, raw->a_str); - break; - case MTR_ARG_TYPE_STRING_COPY: - if (strlen(raw->a_str) > 700) { - snprintf(arg_buf, ARRAY_SIZE(arg_buf), "\"%s\":\"%.*s\"", raw->arg_name, 700, raw->a_str); - } else { - snprintf(arg_buf, ARRAY_SIZE(arg_buf), "\"%s\":\"%s\"", raw->arg_name, raw->a_str); - } - break; - case MTR_ARG_TYPE_NONE: - arg_buf[0] = '\0'; - break; - } - if (raw->id) { - switch (raw->ph) { - case 'S': - case 'T': - case 'F': - // TODO: Support full 64-bit pointers - snprintf(id_buf, ARRAY_SIZE(id_buf), ",\"id\":\"0x%08x\"", (uint32_t)(uintptr_t)raw->id); - break; - case 'X': - snprintf(id_buf, ARRAY_SIZE(id_buf), ",\"dur\":%i", (int)raw->a_double); - break; - } - } else { - id_buf[0] = 0; - } - const char *cat = raw->cat; -#ifdef _WIN32 - // On Windows, we often end up with backslashes in category. - char temp[256]; - { - int len = (int)strlen(cat); - int i; - if (len > 255) len = 255; - for (i = 0; i < len; i++) { - temp[i] = cat[i] == '\\' ? '/' : cat[i]; - } - temp[len] = 0; - cat = temp; - } -#endif - - len = snprintf(linebuf, ARRAY_SIZE(linebuf), "%s{\"cat\":\"%s\",\"pid\":%i,\"tid\":%i,\"ts\":%" PRId64 ",\"ph\":\"%c\",\"name\":\"%s\",\"args\":{%s}%s}", - first_line ? "" : ",\n", - cat, raw->pid, raw->tid, raw->ts - time_offset, raw->ph, raw->name, arg_buf, id_buf); - fwrite(linebuf, 1, len, f); - first_line = 0; - - if (raw->arg_type == MTR_ARG_TYPE_STRING_COPY) { - free((void*)raw->a_str); - } - #ifdef MTR_COPY_EVENT_CATEGORY_AND_NAME - free(raw->name); - free(raw->cat); - #endif - } - - pthread_mutex_lock(&mutex); - is_flushing = is_last; - pthread_mutex_unlock(&mutex); -} - -void mtr_flush() { - mtr_flush_with_state(FALSE); -} - -void internal_mtr_raw_event(const char *category, const char *name, char ph, void *id) { -#ifndef MTR_ENABLED - return; -#endif - pthread_mutex_lock(&mutex); - if (!is_tracing || event_count >= INTERNAL_MINITRACE_BUFFER_SIZE) { - pthread_mutex_unlock(&mutex); - return; - } - raw_event_t *ev = &event_buffer[event_count]; - ++event_count; - pthread_mutex_lock(&event_mutex); - ++events_in_progress; - pthread_mutex_unlock(&event_mutex); - pthread_mutex_unlock(&mutex); - - double ts = mtr_time_s(); - if (!cur_thread_id) { - cur_thread_id = get_cur_thread_id(); - } - if (!cur_process_id) { - cur_process_id = get_cur_process_id(); - } - -#ifdef MTR_COPY_EVENT_CATEGORY_AND_NAME - const size_t category_len = strlen(category); - ev->cat = malloc(category_len + 1); - strcpy(ev->cat, category); - - const size_t name_len = strlen(name); - ev->name = malloc(name_len + 1); - strcpy(ev->name, name); - -#else - ev->cat = category; - ev->name = name; -#endif - - ev->id = id; - ev->ph = ph; - if (ev->ph == 'X') { - double x; - memcpy(&x, id, sizeof(double)); - ev->ts = (int64_t)(x * 1000000); - ev->a_double = (ts - x) * 1000000; - } else { - ev->ts = (int64_t)(ts * 1000000); - } - ev->tid = cur_thread_id; - ev->pid = cur_process_id; - ev->arg_type = MTR_ARG_TYPE_NONE; - - pthread_mutex_lock(&event_mutex); - --events_in_progress; - pthread_mutex_unlock(&event_mutex); -} - -void internal_mtr_raw_event_arg(const char *category, const char *name, char ph, void *id, mtr_arg_type arg_type, const char *arg_name, void *arg_value) { -#ifndef MTR_ENABLED - return; -#endif - pthread_mutex_lock(&mutex); - if (!is_tracing || event_count >= INTERNAL_MINITRACE_BUFFER_SIZE) { - pthread_mutex_unlock(&mutex); - return; - } - raw_event_t *ev = &event_buffer[event_count]; - ++event_count; - pthread_mutex_lock(&event_mutex); - ++events_in_progress; - pthread_mutex_unlock(&event_mutex); - pthread_mutex_unlock(&mutex); - - if (!cur_thread_id) { - cur_thread_id = get_cur_thread_id(); - } - if (!cur_process_id) { - cur_process_id = get_cur_process_id(); - } - double ts = mtr_time_s(); - -#ifdef MTR_COPY_EVENT_CATEGORY_AND_NAME - const size_t category_len = strlen(category); - ev->cat = malloc(category_len + 1); - strcpy(ev->cat, category); - - const size_t name_len = strlen(name); - ev->name = malloc(name_len + 1); - strcpy(ev->name, name); - -#else - ev->cat = category; - ev->name = name; -#endif - - ev->id = id; - ev->ts = (int64_t)(ts * 1000000); - ev->ph = ph; - ev->tid = cur_thread_id; - ev->pid = cur_process_id; - ev->arg_type = arg_type; - ev->arg_name = arg_name; - switch (arg_type) { - case MTR_ARG_TYPE_INT: ev->a_int = (int)(uintptr_t)arg_value; break; - case MTR_ARG_TYPE_STRING_CONST: ev->a_str = (const char*)arg_value; break; - case MTR_ARG_TYPE_STRING_COPY: ev->a_str = strdup((const char*)arg_value); break; - case MTR_ARG_TYPE_NONE: break; - } - - pthread_mutex_lock(&event_mutex); - --events_in_progress; - pthread_mutex_unlock(&event_mutex); -} - diff --git a/src/third_party/minitrace.h b/src/third_party/minitrace.h deleted file mode 100644 index 2047eedb..00000000 --- a/src/third_party/minitrace.h +++ /dev/null @@ -1,270 +0,0 @@ -// Minitrace -// -// Copyright 2014 by Henrik Rydgård -// http://www.github.com/hrydgard/minitrace -// Released under the MIT license. -// -// Ultra-light dependency free library for performance tracing C/C++ applications. -// Produces traces compatible with Google Chrome's trace viewer. -// Simply open "about:tracing" in Chrome and load the produced JSON. -// -// This contains far less template magic than the original libraries from Chrome -// because this is meant to be usable from C. -// -// See README.md for a tutorial. -// -// The trace format is documented here: -// https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/edit -// More: -// http://www.altdevblogaday.com/2012/08/21/using-chrometracing-to-view-your-inline-profiling-data/ - -#ifndef MINITRACE_H -#define MINITRACE_H - -#include - -// If MTR_ENABLED is not defined, Minitrace does nothing and has near zero overhead. -// Preferably, set this flag in your build system. If you can't just uncomment this line. -// #define MTR_ENABLED - -// By default, will collect up to 1000000 events, then you must flush. -// It's recommended that you simply call mtr_flush on a background thread -// occasionally. It's safe...ish. -#define INTERNAL_MINITRACE_BUFFER_SIZE 1000000 - -#ifdef __cplusplus -extern "C" { -#endif - -// Initializes Minitrace. Must be called very early during startup of your executable, -// before any MTR_ statements. -void mtr_init(const char *json_file); -// Same as above, but allows passing in a custom stream (FILE *), as returned by -// fopen(). It should be opened for writing, preferably in binary mode to avoid -// processing of line endings (i.e. the "wb" mode). -void mtr_init_from_stream(void *stream); - -// Shuts down minitrace cleanly, flushing the trace buffer. -void mtr_shutdown(void); - -// Lets you enable and disable Minitrace at runtime. -// May cause strange discontinuities in the output. -// Minitrace is enabled on startup by default. -void mtr_start(void); -void mtr_stop(void); - -// Flushes the collected data to disk, clearing the buffer for new data. -void mtr_flush(void); - -// Returns the current time in seconds. Used internally by Minitrace. No caching. -double mtr_time_s(void); - -// Registers a handler that will flush the trace on Ctrl+C. -// Works on Linux and MacOSX, and in Win32 console applications. -void mtr_register_sigint_handler(void); - -// Utility function that should rarely be used. -// If str is semi dynamic, store it permanently in a small pool so we don't need to malloc it. -// The pool fills up fast though and performance isn't great. -// Returns a fixed string if the pool is full. -const char *mtr_pool_string(const char *str); - -// Commented-out types will be supported in the future. -typedef enum { - MTR_ARG_TYPE_NONE = 0, - MTR_ARG_TYPE_INT = 1, // I - // MTR_ARG_TYPE_FLOAT = 2, // TODO - // MTR_ARG_TYPE_DOUBLE = 3, // TODO - MTR_ARG_TYPE_STRING_CONST = 8, // C - MTR_ARG_TYPE_STRING_COPY = 9, - // MTR_ARG_TYPE_JSON_COPY = 10, -} mtr_arg_type; - -// TODO: Add support for more than one argument (metadata) per event -// Having more costs speed and memory. -#define MTR_MAX_ARGS 1 - -// Only use the macros to call these. -void internal_mtr_raw_event(const char *category, const char *name, char ph, void *id); -void internal_mtr_raw_event_arg(const char *category, const char *name, char ph, void *id, mtr_arg_type arg_type, const char *arg_name, void *arg_value); - -#ifdef MTR_ENABLED - -// c - category. Can be filtered by in trace viewer (or at least that's the intention). -// A good use is to pass __FILE__, there are macros further below that will do it for you. -// n - name. Pass __FUNCTION__ in most cases, unless you are marking up parts of one. - -// Scopes. In C++, use MTR_SCOPE. In C, always match them within the same scope. -#define MTR_BEGIN(c, n) internal_mtr_raw_event(c, n, 'B', 0) -#define MTR_END(c, n) internal_mtr_raw_event(c, n, 'E', 0) -#define MTR_SCOPE(c, n) MTRScopedTrace ____mtr_scope(c, n) -#define MTR_SCOPE_LIMIT(c, n, l) MTRScopedTraceLimit ____mtr_scope(c, n, l) - -// Async events. Can span threads. ID identifies which events to connect in the view. -#define MTR_START(c, n, id) internal_mtr_raw_event(c, n, 'S', (void *)(id)) -#define MTR_STEP(c, n, id, step) internal_mtr_raw_event_arg(c, n, 'T', (void *)(id), MTR_ARG_TYPE_STRING_CONST, "step", (void *)(step)) -#define MTR_FINISH(c, n, id) internal_mtr_raw_event(c, n, 'F', (void *)(id)) - -// Flow events. Like async events, but displayed in a more fancy way in the viewer. -#define MTR_FLOW_START(c, n, id) internal_mtr_raw_event(c, n, 's', (void *)(id)) -#define MTR_FLOW_STEP(c, n, id, step) internal_mtr_raw_event_arg(c, n, 't', (void *)(id), MTR_ARG_TYPE_STRING_CONST, "step", (void *)(step)) -#define MTR_FLOW_FINISH(c, n, id) internal_mtr_raw_event(c, n, 'f', (void *)(id)) - -// The same macros, but with a single named argument which shows up as metadata in the viewer. -// _I for int. -// _C is for a const string arg. -// _S will copy the string, freeing on flush (expensive but sometimes necessary). -// but required if the string was generated dynamically. - -// Note that it's fine to match BEGIN_S with END and BEGIN with END_S, etc. -#define MTR_BEGIN_C(c, n, aname, astrval) internal_mtr_raw_event_arg(c, n, 'B', 0, MTR_ARG_TYPE_STRING_CONST, aname, (void *)(astrval)) -#define MTR_END_C(c, n, aname, astrval) internal_mtr_raw_event_arg(c, n, 'E', 0, MTR_ARG_TYPE_STRING_CONST, aname, (void *)(astrval)) -#define MTR_SCOPE_C(c, n, aname, astrval) MTRScopedTraceArg ____mtr_scope(c, n, MTR_ARG_TYPE_STRING_CONST, aname, (void *)(astrval)) - -#define MTR_BEGIN_S(c, n, aname, astrval) internal_mtr_raw_event_arg(c, n, 'B', 0, MTR_ARG_TYPE_STRING_COPY, aname, (void *)(astrval)) -#define MTR_END_S(c, n, aname, astrval) internal_mtr_raw_event_arg(c, n, 'E', 0, MTR_ARG_TYPE_STRING_COPY, aname, (void *)(astrval)) -#define MTR_SCOPE_S(c, n, aname, astrval) MTRScopedTraceArg ____mtr_scope(c, n, MTR_ARG_TYPE_STRING_COPY, aname, (void *)(astrval)) - -#define MTR_BEGIN_I(c, n, aname, aintval) internal_mtr_raw_event_arg(c, n, 'B', 0, MTR_ARG_TYPE_INT, aname, (void*)(intptr_t)(aintval)) -#define MTR_END_I(c, n, aname, aintval) internal_mtr_raw_event_arg(c, n, 'E', 0, MTR_ARG_TYPE_INT, aname, (void*)(intptr_t)(aintval)) -#define MTR_SCOPE_I(c, n, aname, aintval) MTRScopedTraceArg ____mtr_scope(c, n, MTR_ARG_TYPE_INT, aname, (void*)(intptr_t)(aintval)) - -// Instant events. For things with no duration. -#define MTR_INSTANT(c, n) internal_mtr_raw_event(c, n, 'I', 0) -#define MTR_INSTANT_C(c, n, aname, astrval) internal_mtr_raw_event_arg(c, n, 'I', 0, MTR_ARG_TYPE_STRING_CONST, aname, (void *)(astrval)) -#define MTR_INSTANT_I(c, n, aname, aintval) internal_mtr_raw_event_arg(c, n, 'I', 0, MTR_ARG_TYPE_INT, aname, (void *)(aintval)) - -// Counters (can't do multi-value counters yet) -#define MTR_COUNTER(c, n, val) internal_mtr_raw_event_arg(c, n, 'C', 0, MTR_ARG_TYPE_INT, n, (void *)(intptr_t)(val)) - -// Metadata. Call at the start preferably. Must be const strings. - -#define MTR_META_PROCESS_NAME(n) internal_mtr_raw_event_arg("", "process_name", 'M', 0, MTR_ARG_TYPE_STRING_COPY, "name", (void *)(n)) -#define MTR_META_THREAD_NAME(n) internal_mtr_raw_event_arg("", "thread_name", 'M', 0, MTR_ARG_TYPE_STRING_COPY, "name", (void *)(n)) -#define MTR_META_THREAD_SORT_INDEX(i) internal_mtr_raw_event_arg("", "thread_sort_index", 'M', 0, MTR_ARG_TYPE_INT, "sort_index", (void *)(i)) - -#else - -#define MTR_BEGIN(c, n) -#define MTR_END(c, n) -#define MTR_SCOPE(c, n) -#define MTR_START(c, n, id) -#define MTR_STEP(c, n, id, step) -#define MTR_FINISH(c, n, id) -#define MTR_FLOW_START(c, n, id) -#define MTR_FLOW_STEP(c, n, id, step) -#define MTR_FLOW_FINISH(c, n, id) -#define MTR_INSTANT(c, n) - -#define MTR_BEGIN_C(c, n, aname, astrval) -#define MTR_END_C(c, n, aname, astrval) -#define MTR_SCOPE_C(c, n, aname, astrval) - -#define MTR_BEGIN_S(c, n, aname, astrval) -#define MTR_END_S(c, n, aname, astrval) -#define MTR_SCOPE_S(c, n, aname, astrval) - -#define MTR_BEGIN_I(c, n, aname, aintval) -#define MTR_END_I(c, n, aname, aintval) -#define MTR_SCOPE_I(c, n, aname, aintval) - -#define MTR_INSTANT(c, n) -#define MTR_INSTANT_C(c, n, aname, astrval) -#define MTR_INSTANT_I(c, n, aname, aintval) - -// Counters (can't do multi-value counters yet) -#define MTR_COUNTER(c, n, val) - -// Metadata. Call at the start preferably. Must be const strings. - -#define MTR_META_PROCESS_NAME(n) - -#define MTR_META_THREAD_NAME(n) -#define MTR_META_THREAD_SORT_INDEX(i) - -#endif - -// Shortcuts for simple function timing with automatic categories and names. - -#define MTR_BEGIN_FUNC() MTR_BEGIN(__FILE__, __FUNCTION__) -#define MTR_END_FUNC() MTR_END(__FILE__, __FUNCTION__) -#define MTR_SCOPE_FUNC() MTR_SCOPE(__FILE__, __FUNCTION__) -#define MTR_INSTANT_FUNC() MTR_INSTANT(__FILE__, __FUNCTION__) -#define MTR_SCOPE_FUNC_LIMIT_S(l) MTRScopedTraceLimit ____mtr_scope(__FILE__, __FUNCTION__, l) -#define MTR_SCOPE_FUNC_LIMIT_MS(l) MTRScopedTraceLimit ____mtr_scope(__FILE__, __FUNCTION__, (double)l * 0.000001) - -// Same, but with a single argument of the usual types. -#define MTR_BEGIN_FUNC_S(aname, arg) MTR_BEGIN_S(__FILE__, __FUNCTION__, aname, arg) -#define MTR_END_FUNC_S(aname, arg) MTR_END_S(__FILE__, __FUNCTION__, aname, arg) -#define MTR_SCOPE_FUNC_S(aname, arg) MTR_SCOPE_S(__FILE__, __FUNCTION__, aname, arg) - -#define MTR_BEGIN_FUNC_C(aname, arg) MTR_BEGIN_C(__FILE__, __FUNCTION__, aname, arg) -#define MTR_END_FUNC_C(aname, arg) MTR_END_C(__FILE__, __FUNCTION__, aname, arg) -#define MTR_SCOPE_FUNC_C(aname, arg) MTR_SCOPE_C(__FILE__, __FUNCTION__, aname, arg) - -#define MTR_BEGIN_FUNC_I(aname, arg) MTR_BEGIN_I(__FILE__, __FUNCTION__, aname, arg) -#define MTR_END_FUNC_I(aname, arg) MTR_END_I(__FILE__, __FUNCTION__, aname, arg) -#define MTR_SCOPE_FUNC_I(aname, arg) MTR_SCOPE_I(__FILE__, __FUNCTION__, aname, arg) - -#ifdef __cplusplus -} - -#ifdef MTR_ENABLED -// These are optimized to use X events (combined B and E). Much easier to do in C++ than in C. -class MTRScopedTrace { -public: - MTRScopedTrace(const char *category, const char *name) - : category_(category), name_(name) { - start_time_ = mtr_time_s(); - } - ~MTRScopedTrace() { - internal_mtr_raw_event(category_, name_, 'X', &start_time_); - } - -private: - const char *category_; - const char *name_; - double start_time_; -}; - -// Only outputs a block if execution time exceeded the limit. -// TODO: This will effectively call mtr_time_s twice at the end, which is bad. -class MTRScopedTraceLimit { -public: - MTRScopedTraceLimit(const char *category, const char *name, double limit_s) - : category_(category), name_(name), limit_(limit_s) { - start_time_ = mtr_time_s(); - } - ~MTRScopedTraceLimit() { - double end_time = mtr_time_s(); - if (end_time - start_time_ >= limit_) { - internal_mtr_raw_event(category_, name_, 'X', &start_time_); - } - } - -private: - const char *category_; - const char *name_; - double start_time_; - double limit_; -}; - -class MTRScopedTraceArg { -public: - MTRScopedTraceArg(const char *category, const char *name, mtr_arg_type arg_type, const char *arg_name, void *arg_value) - : category_(category), name_(name) { - internal_mtr_raw_event_arg(category, name, 'B', 0, arg_type, arg_name, arg_value); - } - ~MTRScopedTraceArg() { - internal_mtr_raw_event(category_, name_, 'E', 0); - } - -private: - const char *category_; - const char *name_; -}; -#endif - -#endif - -#endif