Deprecate omnitrace use thread sampling (#68)
* Deprecate OMNITRACE_USE_THREAD_SAMPLING * Reworked config based on OMNITRACE_MODE - config::set_default_setting_value(...) - config::get_mode() is now dynamically deduced - moved tweaking defaults from library.cpp to config::configure_mode_settings(...) - timemory submodule update fixing vsetting issue * runtime.md update * revert accidental lambda name change * Reintroduce (deprecated) OMNITRACE_ROCM_SMI_DEVICES - add handle_deprecated_setting(...) for this deprecated setting
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
cfa16cbe2f
Коммит
27e4e82376
@@ -23,6 +23,7 @@
|
||||
#include "library/config.hpp"
|
||||
#include "library/debug.hpp"
|
||||
#include "library/defines.hpp"
|
||||
#include "library/gpu.hpp"
|
||||
|
||||
#include <timemory/backends/dmp.hpp>
|
||||
#include <timemory/backends/mpi.hpp>
|
||||
@@ -72,7 +73,7 @@ get_setting_name(std::string _v)
|
||||
}
|
||||
|
||||
#define OMNITRACE_CONFIG_SETTING(TYPE, ENV_NAME, DESCRIPTION, INITIAL_VALUE, ...) \
|
||||
{ \
|
||||
[&]() { \
|
||||
auto _ret = _config->insert<TYPE, TYPE>( \
|
||||
ENV_NAME, get_setting_name(ENV_NAME), DESCRIPTION, INITIAL_VALUE, \
|
||||
std::set<std::string>{ "custom", "omnitrace", "omnitrace_library", \
|
||||
@@ -80,23 +81,25 @@ get_setting_name(std::string _v)
|
||||
if(!_ret.second) \
|
||||
OMNITRACE_PRINT("Warning! Duplicate setting: %s / %s\n", \
|
||||
get_setting_name(ENV_NAME).c_str(), ENV_NAME); \
|
||||
}
|
||||
return _config->find(ENV_NAME)->second; \
|
||||
}()
|
||||
|
||||
// below does not include "omnitrace_library"
|
||||
#define OMNITRACE_CONFIG_EXT_SETTING(TYPE, ENV_NAME, DESCRIPTION, INITIAL_VALUE, ...) \
|
||||
{ \
|
||||
[&]() { \
|
||||
auto _ret = _config->insert<TYPE, TYPE>( \
|
||||
ENV_NAME, get_setting_name(ENV_NAME), DESCRIPTION, INITIAL_VALUE, \
|
||||
std::set<std::string>{ "custom", "omnitrace", __VA_ARGS__ }); \
|
||||
if(!_ret.second) \
|
||||
OMNITRACE_PRINT("Warning! Duplicate setting: %s / %s\n", \
|
||||
get_setting_name(ENV_NAME).c_str(), ENV_NAME); \
|
||||
}
|
||||
return _config->find(ENV_NAME)->second; \
|
||||
}()
|
||||
|
||||
// setting + command line option
|
||||
#define OMNITRACE_CONFIG_CL_SETTING(TYPE, ENV_NAME, DESCRIPTION, INITIAL_VALUE, \
|
||||
CMD_LINE, ...) \
|
||||
{ \
|
||||
[&]() { \
|
||||
auto _ret = _config->insert<TYPE, TYPE>( \
|
||||
ENV_NAME, get_setting_name(ENV_NAME), DESCRIPTION, INITIAL_VALUE, \
|
||||
std::set<std::string>{ "custom", "omnitrace", "omnitrace_library", \
|
||||
@@ -105,7 +108,8 @@ get_setting_name(std::string _v)
|
||||
if(!_ret.second) \
|
||||
OMNITRACE_PRINT("Warning! Duplicate setting: %s / %s\n", \
|
||||
get_setting_name(ENV_NAME).c_str(), ENV_NAME); \
|
||||
}
|
||||
return _config->find(ENV_NAME)->second; \
|
||||
}()
|
||||
} // namespace
|
||||
|
||||
inline namespace config
|
||||
@@ -159,6 +163,12 @@ configure_settings(bool _init)
|
||||
auto _omnitrace_debug = _config->get<bool>("OMNITRACE_DEBUG");
|
||||
if(_omnitrace_debug) tim::set_env("TIMEMORY_DEBUG_SETTINGS", "1", 0);
|
||||
|
||||
OMNITRACE_CONFIG_SETTING(
|
||||
std::string, "OMNITRACE_MODE",
|
||||
"Data collection mode. Used to set default values for OMNITRACE_USE_* options. "
|
||||
"Typically set by omnitrace binary instrumenter.",
|
||||
"trace", "backend");
|
||||
|
||||
OMNITRACE_CONFIG_SETTING(bool, "OMNITRACE_CI",
|
||||
"Enable some runtime validation checks (typically enabled "
|
||||
"for continuous integration)",
|
||||
@@ -188,9 +198,15 @@ configure_settings(bool _init)
|
||||
"backend", "sampling");
|
||||
|
||||
OMNITRACE_CONFIG_SETTING(bool, "OMNITRACE_USE_THREAD_SAMPLING",
|
||||
"Enable a background thread which samples system metrics "
|
||||
"such as the CPU/GPU freq, power, etc.",
|
||||
true, "backend", "sampling", "thread_sampling");
|
||||
"[DEPRECATED] Renamed to OMNITRACE_USE_PROCESS_SAMPLING",
|
||||
true, "backend", "sampling", "process_sampling",
|
||||
"deprecated");
|
||||
|
||||
OMNITRACE_CONFIG_SETTING(
|
||||
bool, "OMNITRACE_USE_PROCESS_SAMPLING",
|
||||
"Enable a background thread which samples process-level and system metrics "
|
||||
"such as the CPU/GPU freq, power, memory usage, etc.",
|
||||
true, "backend", "sampling", "process_sampling");
|
||||
|
||||
OMNITRACE_CONFIG_SETTING(
|
||||
bool, "OMNITRACE_USE_PID",
|
||||
@@ -221,27 +237,31 @@ configure_settings(bool _init)
|
||||
OMNITRACE_CONFIG_SETTING(
|
||||
double, "OMNITRACE_SAMPLING_FREQ",
|
||||
"Number of software interrupts per second when OMNITTRACE_USE_SAMPLING=ON", 10.0,
|
||||
"sampling", "thread_sampling");
|
||||
"sampling", "process_sampling");
|
||||
|
||||
OMNITRACE_CONFIG_SETTING(
|
||||
double, "OMNITRACE_SAMPLING_DELAY",
|
||||
"Number of seconds to wait before the first sampling signal is delivered, "
|
||||
"increasing this value can fix deadlocks during init",
|
||||
0.5, "sampling", "thread_sampling");
|
||||
0.5, "sampling", "process_sampling");
|
||||
|
||||
OMNITRACE_CONFIG_SETTING(
|
||||
std::string, "OMNITRACE_SAMPLING_CPUS",
|
||||
"CPUs to collect frequency information for. Values should be separated by commas "
|
||||
"and can be explicit or ranges, e.g. 0,1,5-8. An empty value implies 'all' and "
|
||||
"'none' suppresses all CPU frequency sampling",
|
||||
"", "thread_sampling");
|
||||
"", "process_sampling");
|
||||
|
||||
OMNITRACE_CONFIG_SETTING(std::string, "OMNITRACE_ROCM_SMI_DEVICES",
|
||||
"[DEPRECATED] Renamed to OMNITRACE_SAMPLING_GPUS", "all",
|
||||
"rocm_smi", "rocm", "process_sampling");
|
||||
|
||||
OMNITRACE_CONFIG_SETTING(
|
||||
std::string, "OMNITRACE_SAMPLING_GPUS",
|
||||
"Devices to query when OMNITRACE_USE_ROCM_SMI=ON. Values should be separated by "
|
||||
"commas and can be explicit or ranges, e.g. 0,1,5-8. An empty value implies "
|
||||
"'all' and 'none' suppresses all GPU sampling",
|
||||
"all", "rocm_smi", "rocm", "thread_sampling");
|
||||
"all", "rocm_smi", "rocm", "process_sampling");
|
||||
|
||||
auto _backend = tim::get_env_choice<std::string>(
|
||||
"OMNITRACE_PERFETTO_BACKEND",
|
||||
@@ -253,10 +273,8 @@ configure_settings(bool _init)
|
||||
OMNITRACE_CONFIG_SETTING(std::string, "OMNITRACE_PERFETTO_BACKEND",
|
||||
"Specify the perfetto backend to activate. Options are: "
|
||||
"'inprocess', 'system', or 'all'",
|
||||
_backend, "perfetto");
|
||||
|
||||
_config->find("OMNITRACE_PERFETTO_BACKEND")
|
||||
->second->set_choices({ "inprocess", "system", "all" });
|
||||
_backend, "perfetto")
|
||||
->set_choices({ "inprocess", "system", "all" });
|
||||
|
||||
OMNITRACE_CONFIG_SETTING(bool, "OMNITRACE_CRITICAL_TRACE",
|
||||
"Enable generation of the critical trace", false, "backend",
|
||||
@@ -325,10 +343,8 @@ configure_settings(bool _init)
|
||||
std::string, "OMNITRACE_PERFETTO_FILL_POLICY",
|
||||
"Behavior when perfetto buffer is full. 'discard' will ignore new entries, "
|
||||
"'ring_buffer' will overwrite old entries",
|
||||
"discard", "perfetto", "data");
|
||||
|
||||
_config->find("OMNITRACE_PERFETTO_FILL_POLICY")
|
||||
->second->set_choices({ "fill", "discard" });
|
||||
"discard", "perfetto", "data")
|
||||
->set_choices({ "fill", "discard" });
|
||||
|
||||
OMNITRACE_CONFIG_EXT_SETTING(int64_t, "OMNITRACE_CRITICAL_TRACE_COUNT",
|
||||
"Number of critical trace to export (0 == all)", 0,
|
||||
@@ -359,7 +375,9 @@ configure_settings(bool _init)
|
||||
OMNITRACE_CONFIG_SETTING(std::string, "OMNITRACE_OUTPUT_FILE", "Perfetto filename",
|
||||
"", "perfetto", "io", "filename");
|
||||
|
||||
// set the defaults
|
||||
_config->get_flamegraph_output() = false;
|
||||
_config->get_ctest_notes() = false;
|
||||
_config->get_cout_output() = false;
|
||||
_config->get_file_output() = true;
|
||||
_config->get_json_output() = true;
|
||||
@@ -471,6 +489,10 @@ configure_settings(bool _init)
|
||||
_combine_perfetto_traces->second->set(_config->get<bool>("collapse_processes"));
|
||||
}
|
||||
|
||||
handle_deprecated_setting("OMNITRACE_ROCM_SMI_DEVICES", "OMNITRACE_SAMPLING_GPUS");
|
||||
handle_deprecated_setting("OMNITRACE_USE_THREAD_SAMPLING",
|
||||
"OMNITRACE_USE_PROCESS_SAMPLING");
|
||||
|
||||
scope::get_fields()[scope::flat::value] = _config->get_flat_profile();
|
||||
scope::get_fields()[scope::timeline::value] = _config->get_timeline_profile();
|
||||
|
||||
@@ -479,8 +501,88 @@ configure_settings(bool _init)
|
||||
#if !defined(TIMEMORY_USE_MPI) && defined(TIMEMORY_USE_MPI_HEADERS)
|
||||
if(tim::dmp::is_initialized()) settings::default_process_suffix() = tim::dmp::rank();
|
||||
#endif
|
||||
OMNITRACE_CONDITIONAL_BASIC_PRINT(get_verbose_env() > 0, "configuration complete\n");
|
||||
|
||||
auto _dl_verbose = _config->find("OMNITRACE_DL_VERBOSE");
|
||||
tim::set_env(std::string{ _dl_verbose->first }, _dl_verbose->second->as_string(), 0);
|
||||
|
||||
#if !defined(TIMEMORY_USE_MPI) || TIMEMORY_USE_MPI == 0
|
||||
_config->disable("OMNITRACE_PERFETTO_COMBINE_TRACES");
|
||||
#endif
|
||||
|
||||
configure_mode_settings();
|
||||
configure_signal_handler();
|
||||
configure_disabled_settings();
|
||||
|
||||
OMNITRACE_CONDITIONAL_BASIC_PRINT(get_verbose_env() > 0, "configuration complete\n");
|
||||
}
|
||||
|
||||
void
|
||||
configure_mode_settings()
|
||||
{
|
||||
auto _set = [](const std::string& _name, bool _v) {
|
||||
if(!set_setting_value(_name, _v))
|
||||
{
|
||||
OMNITRACE_VERBOSE(
|
||||
4, "[configure_mode_settings] No configuration setting named '%s'...\n",
|
||||
_name.data());
|
||||
}
|
||||
else
|
||||
{
|
||||
OMNITRACE_VERBOSE(
|
||||
1, "[configure_mode_settings] Overriding %s to %s in %s mode...\n",
|
||||
_name.c_str(), JOIN("", std::boolalpha, _v).c_str(),
|
||||
std::to_string(get_mode()).c_str());
|
||||
}
|
||||
};
|
||||
|
||||
if(get_mode() == Mode::Coverage)
|
||||
{
|
||||
set_default_setting_value("OMNITRACE_USE_CODE_COVERAGE", true);
|
||||
_set("OMNITRACE_USE_PERFETTO", false);
|
||||
_set("OMNITRACE_USE_TIMEMORY", false);
|
||||
_set("OMNITRACE_USE_ROCM_SMI", false);
|
||||
_set("OMNITRACE_USE_ROCTRACER", false);
|
||||
_set("OMNITRACE_USE_KOKKOSP", false);
|
||||
_set("OMNITRACE_USE_OMPT", false);
|
||||
_set("OMNITRACE_USE_SAMPLING", false);
|
||||
_set("OMNITRACE_USE_PROCESS_SAMPLING", false);
|
||||
_set("OMNITRACE_CRITICAL_TRACE", false);
|
||||
}
|
||||
else if(get_mode() == Mode::Sampling)
|
||||
{
|
||||
set_default_setting_value("OMNITRACE_USE_SAMPLING", true);
|
||||
set_default_setting_value("OMNITRACE_USE_PROCESS_SAMPLING", true);
|
||||
_set("OMNITRACE_CRITICAL_TRACE", false);
|
||||
}
|
||||
|
||||
if(gpu::device_count() == 0)
|
||||
{
|
||||
OMNITRACE_VERBOSE_F(
|
||||
1, "No HIP devices were found: disabling roctracer and rocm_smi...\n");
|
||||
get_use_roctracer() = false;
|
||||
get_use_rocm_smi() = false;
|
||||
}
|
||||
|
||||
get_instrumentation_interval() = std::max<size_t>(get_instrumentation_interval(), 1);
|
||||
|
||||
if(get_use_kokkosp())
|
||||
{
|
||||
auto _force = 0;
|
||||
auto _current_kokkosp_lib = tim::get_env<std::string>("KOKKOS_PROFILE_LIBRARY");
|
||||
if(std::regex_search(_current_kokkosp_lib, std::regex{ "libtimemory\\." }))
|
||||
_force = 1;
|
||||
tim::set_env("KOKKOS_PROFILE_LIBRARY", "libomnitrace.so", _force);
|
||||
}
|
||||
|
||||
// recycle all subsequent thread ids
|
||||
threading::recycle_ids() =
|
||||
tim::get_env<bool>("OMNITRACE_RECYCLE_TIDS", !get_use_sampling());
|
||||
}
|
||||
|
||||
void
|
||||
configure_signal_handler()
|
||||
{
|
||||
auto _config = settings::shared_instance();
|
||||
auto _ignore_dyninst_trampoline =
|
||||
tim::get_env("OMNITRACE_IGNORE_DYNINST_TRAMPOLINE", false);
|
||||
// this is how dyninst looks up the env variable
|
||||
@@ -533,8 +635,14 @@ configure_settings(bool _init)
|
||||
_old_handler = signal(_dyninst_trampoline_signal,
|
||||
static_cast<signal_handler_t>(_trampoline_handler));
|
||||
}
|
||||
}
|
||||
|
||||
auto _handle_use_option = [](const std::string& _opt, const std::string& _category) {
|
||||
void
|
||||
configure_disabled_settings()
|
||||
{
|
||||
auto _config = settings::shared_instance();
|
||||
auto _handle_use_option = [_config](const std::string& _opt,
|
||||
const std::string& _category) {
|
||||
if(!_config->get<bool>(_opt))
|
||||
{
|
||||
auto _disabled = _config->disable_category(_category);
|
||||
@@ -552,7 +660,7 @@ configure_settings(bool _init)
|
||||
};
|
||||
|
||||
_handle_use_option("OMNITRACE_USE_SAMPLING", "sampling");
|
||||
_handle_use_option("OMNITRACE_USE_THREAD_SAMPLING", "thread_sampling");
|
||||
_handle_use_option("OMNITRACE_USE_PROCESS_SAMPLING", "process_sampling");
|
||||
_handle_use_option("OMNITRACE_USE_KOKKOSP", "kokkos");
|
||||
_handle_use_option("OMNITRACE_USE_PERFETTO", "perfetto");
|
||||
_handle_use_option("OMNITRACE_USE_TIMEMORY", "timemory");
|
||||
@@ -573,31 +681,79 @@ configure_settings(bool _init)
|
||||
_config->disable_category("ompt");
|
||||
#endif
|
||||
|
||||
// user bundle components
|
||||
_config->disable_category("throttle");
|
||||
|
||||
// user bundle components
|
||||
_config->disable("components");
|
||||
_config->disable("global_components");
|
||||
_config->disable("ompt_components");
|
||||
_config->disable("kokkos_components");
|
||||
_config->disable("trace_components");
|
||||
_config->disable("profiler_components");
|
||||
|
||||
// miscellaneous
|
||||
_config->disable("destructor_report");
|
||||
_config->disable("stack_clearing");
|
||||
_config->disable("add_secondary");
|
||||
|
||||
// output fields
|
||||
_config->disable("auto_output");
|
||||
_config->disable("file_output");
|
||||
_config->disable("plot_output");
|
||||
_config->disable("dart_output");
|
||||
_config->disable("flamegraph_output");
|
||||
_config->disable("separator_freq");
|
||||
_config->disable("width");
|
||||
_config->disable("max_width");
|
||||
}
|
||||
|
||||
auto _dl_verbose = _config->find("OMNITRACE_DL_VERBOSE");
|
||||
tim::set_env(std::string{ _dl_verbose->first }, _dl_verbose->second->as_string(), 0);
|
||||
void
|
||||
handle_deprecated_setting(const std::string& _old, const std::string& _new, int _verbose)
|
||||
{
|
||||
auto _config = settings::shared_instance();
|
||||
auto _old_setting = _config->find(_old);
|
||||
auto _new_setting = _config->find(_new);
|
||||
|
||||
#if !defined(TIMEMORY_USE_MPI) || TIMEMORY_USE_MPI == 0
|
||||
_config->disable("OMNITRACE_PERFETTO_COMBINE_TRACES");
|
||||
#endif
|
||||
if(_old_setting == _config->end()) return;
|
||||
|
||||
OMNITRACE_CI_THROW(_new_setting == _config->end(),
|
||||
"New configuration setting not found: '%s'", _new.c_str());
|
||||
|
||||
if(_old_setting->second->get_environ_updated() ||
|
||||
_old_setting->second->get_config_updated())
|
||||
{
|
||||
auto _separator = [_verbose]() {
|
||||
std::array<char, 79> _v = {};
|
||||
_v.fill('=');
|
||||
_v.back() = '\0';
|
||||
OMNITRACE_VERBOSE(_verbose, "#%s#\n", _v.data());
|
||||
};
|
||||
_separator();
|
||||
OMNITRACE_VERBOSE(_verbose, "#\n");
|
||||
OMNITRACE_VERBOSE(_verbose, "# DEPRECATION NOTICE:\n");
|
||||
OMNITRACE_VERBOSE(_verbose, "# %s is deprecated!\n", _old.c_str());
|
||||
OMNITRACE_VERBOSE(_verbose, "# Use %s instead!\n", _new.c_str());
|
||||
|
||||
if(!_new_setting->second->get_environ_updated() &&
|
||||
!_new_setting->second->get_config_updated())
|
||||
{
|
||||
auto _before = _new_setting->second->as_string();
|
||||
_new_setting->second->parse(_old_setting->second->as_string());
|
||||
auto _after = _new_setting->second->as_string();
|
||||
|
||||
if(_before != _after)
|
||||
{
|
||||
std::string _cause =
|
||||
(_old_setting->second->get_environ_updated()) ? "environ" : "config";
|
||||
OMNITRACE_VERBOSE(_verbose, "#\n");
|
||||
OMNITRACE_VERBOSE(_verbose, "# %s :: '%s' -> '%s'\n", _new.c_str(),
|
||||
_before.c_str(), _after.c_str());
|
||||
OMNITRACE_VERBOSE(_verbose, "# via %s (%s)\n", _old.c_str(),
|
||||
_cause.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
OMNITRACE_VERBOSE(_verbose, "#\n");
|
||||
_separator();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -653,6 +809,9 @@ print_settings(
|
||||
std::sort(_data.begin(), _data.end(), [](const auto& lhs, const auto& rhs) {
|
||||
auto _npos = std::string::npos;
|
||||
// OMNITRACE_CONFIG_FILE always first
|
||||
if(lhs.at(0) == "OMNITRACE_MODE") return true;
|
||||
if(rhs.at(0) == "OMNITRACE_MODE") return false;
|
||||
// OMNITRACE_CONFIG_FILE always second
|
||||
if(lhs.at(0).find("OMNITRACE_CONFIG") != _npos) return true;
|
||||
if(rhs.at(0).find("OMNITRACE_CONFIG") != _npos) return false;
|
||||
// OMNITRACE_USE_* prioritized
|
||||
@@ -756,7 +915,8 @@ get_config_file()
|
||||
Mode
|
||||
get_mode()
|
||||
{
|
||||
static auto _v = []() {
|
||||
if(!settings_are_configured())
|
||||
{
|
||||
auto _mode = tim::get_env_choice<std::string>(
|
||||
"OMNITRACE_MODE", "trace", { "trace", "sampling", "coverage" });
|
||||
if(_mode == "sampling")
|
||||
@@ -764,8 +924,26 @@ get_mode()
|
||||
else if(_mode == "coverage")
|
||||
return Mode::Coverage;
|
||||
return Mode::Trace;
|
||||
}();
|
||||
return _v;
|
||||
}
|
||||
static auto _m =
|
||||
std::unordered_map<std::string_view, Mode>{ { "trace", Mode::Trace },
|
||||
{ "sampling", Mode::Sampling },
|
||||
{ "coverage", Mode::Coverage } };
|
||||
static auto _v = get_config()->find("OMNITRACE_MODE");
|
||||
try
|
||||
{
|
||||
return _m.at(static_cast<tim::tsettings<std::string>&>(*_v->second).get());
|
||||
} catch(std::runtime_error& _e)
|
||||
{
|
||||
auto _mode = static_cast<tim::tsettings<std::string>&>(*_v->second).get();
|
||||
std::stringstream _ss{};
|
||||
for(const auto& itr : _v->second->get_choices())
|
||||
_ss << ", " << itr;
|
||||
auto _msg = (_ss.str().length() > 2) ? _ss.str().substr(2) : std::string{};
|
||||
OMNITRACE_THROW("[%s] invalid mode %s. Choices: %s\n", __FUNCTION__,
|
||||
_mode.c_str(), _msg.c_str());
|
||||
}
|
||||
return Mode::Trace;
|
||||
}
|
||||
|
||||
bool&
|
||||
@@ -818,8 +996,10 @@ get_debug()
|
||||
bool
|
||||
get_debug_sampling()
|
||||
{
|
||||
static bool _v = tim::get_env<bool>("OMNITRACE_DEBUG_SAMPLING", get_debug_env());
|
||||
return (_v || get_debug());
|
||||
static bool _v =
|
||||
tim::get_env<bool>("OMNITRACE_DEBUG_SAMPLING",
|
||||
(settings_are_configured() ? get_debug() : get_debug_env()));
|
||||
return _v;
|
||||
}
|
||||
|
||||
int
|
||||
@@ -888,9 +1068,9 @@ get_use_sampling()
|
||||
}
|
||||
|
||||
bool&
|
||||
get_use_thread_sampling()
|
||||
get_use_process_sampling()
|
||||
{
|
||||
static auto _v = get_config()->find("OMNITRACE_USE_THREAD_SAMPLING");
|
||||
static auto _v = get_config()->find("OMNITRACE_USE_PROCESS_SAMPLING");
|
||||
return static_cast<tim::tsettings<bool>&>(*_v->second).get();
|
||||
}
|
||||
|
||||
@@ -1142,7 +1322,7 @@ get_critical_trace_count()
|
||||
}
|
||||
|
||||
double&
|
||||
get_thread_sampling_freq()
|
||||
get_process_sampling_freq()
|
||||
{
|
||||
static auto _v = std::min<double>(get_sampling_freq(), 1000.0);
|
||||
return _v;
|
||||
|
||||
Ссылка в новой задаче
Block a user