diff options
author | Oleg Lekarev <o.lekarev@samsung.com> | 2023-05-24 18:44:51 +0300 |
---|---|---|
committer | Gleb Balykov/Advanced System SW Lab /SRR/Staff Engineer/Samsung Electronics <g.balykov@samsung.com> | 2023-06-08 16:09:56 +0300 |
commit | 091a13118cd98b90022b48e682eb7b95e4b2d7df (patch) | |
tree | ecff470445982e7323365b3d20d1bfbe5e750d68 | |
parent | f5dbdb98a37d2fb7fe0a5ffc177958dea6233dfe (diff) | |
download | heaptrack-091a13118cd98b90022b48e682eb7b95e4b2d7df.tar.gz heaptrack-091a13118cd98b90022b48e682eb7b95e4b2d7df.tar.bz2 heaptrack-091a13118cd98b90022b48e682eb7b95e4b2d7df.zip |
Configurator manager from file or environment added
-rw-r--r-- | profiler/profiler/src/CMakeLists.txt | 7 | ||||
-rw-r--r-- | profiler/profiler/src/config/commonconfig.h | 23 | ||||
-rw-r--r-- | profiler/profiler/src/config/commonconfigconversions.cpp | 88 | ||||
-rw-r--r-- | profiler/profiler/src/config/commonconfigconversions.h | 28 | ||||
-rw-r--r-- | profiler/profiler/src/config/configurationmanager.cpp | 118 | ||||
-rw-r--r-- | profiler/profiler/src/config/configurationmanager.h | 65 | ||||
-rw-r--r-- | profiler/profiler/src/config/environmentconfigprovider.cpp | 31 | ||||
-rw-r--r-- | profiler/profiler/src/config/environmentconfigprovider.h | 30 | ||||
-rw-r--r-- | profiler/profiler/src/config/fileconfigprovider.cpp | 121 | ||||
-rw-r--r-- | profiler/profiler/src/config/fileconfigprovider.h | 40 | ||||
-rw-r--r-- | profiler/profiler/src/config/profilerconfig.cpp | 61 | ||||
-rw-r--r-- | profiler/profiler/src/config/profilerconfig.h | 52 | ||||
-rw-r--r-- | profiler/profiler/src/profiler.cpp | 57 | ||||
-rw-r--r-- | profiler/profiler/src/profiler.h | 3 |
14 files changed, 683 insertions, 41 deletions
diff --git a/profiler/profiler/src/CMakeLists.txt b/profiler/profiler/src/CMakeLists.txt index 68b27ef..e8f83d5 100644 --- a/profiler/profiler/src/CMakeLists.txt +++ b/profiler/profiler/src/CMakeLists.txt @@ -18,7 +18,12 @@ ENDIF(${CLR_ARCH} MATCHES "x64") set(PROFILER_SOURCES classfactory.cpp profiler.cpp - pal_excerpts.cpp) + pal_excerpts.cpp + config/commonconfigconversions.cpp + config/configurationmanager.cpp + config/environmentconfigprovider.cpp + config/fileconfigprovider.cpp + config/profilerconfig.cpp) set(CLR_INCLUDES ${CLR_SRC_DIR}/src/pal/inc/rt diff --git a/profiler/profiler/src/config/commonconfig.h b/profiler/profiler/src/config/commonconfig.h new file mode 100644 index 0000000..ea7f921 --- /dev/null +++ b/profiler/profiler/src/config/commonconfig.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _COMMON_CONFIG_H_ +#define _COMMON_CONFIG_H_ + +template<typename Target, typename Source> +bool convert(Source, Target&); + +#endif // _COMMON_CONFIG_H_ diff --git a/profiler/profiler/src/config/commonconfigconversions.cpp b/profiler/profiler/src/config/commonconfigconversions.cpp new file mode 100644 index 0000000..4596345 --- /dev/null +++ b/profiler/profiler/src/config/commonconfigconversions.cpp @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <string> + +#include <stdlib.h> +#include <string.h> +#include <errno.h> + +#include <strings.h> + +#include "commonconfigconversions.h" + +template<> +bool convert(const char *str, bool& value) +{ + if ( + strcmp (str, "1") == 0 || + strcasecmp(str, "true") == 0 || + strcasecmp(str, "on") == 0 || + strcasecmp(str, "yes") == 0 || + strcasecmp(str, "enabled") == 0 || + strcasecmp(str, "") == 0 + ) + { + value = true; + return true; + } + else if ( + strcmp (str, "0") == 0 || + strcasecmp(str, "false") == 0 || + strcasecmp(str, "off") == 0 || + strcasecmp(str, "no") == 0 || + strcasecmp(str, "disabled") == 0 + ) + { + value = false; + return true; + } + else + { + fprintf(stderr, "Configuration error: %s has incorrect value for type bool\n", str); + value = false; + return false; + } +} + +template<> +bool convert(const char *str, unsigned long& value) +{ + char *str_end; + + errno = 0; + value = strtoul(str, &str_end, 0); + + if (errno == ERANGE) + { + fprintf(stderr, "Configuration error: %s is out of range for unsigned long\n", str); + return false; + } + + if (str == str_end) + { + fprintf(stderr, "Configuration error: %s has incorrect value for type unsigned long\n", str); + return false; + } + + if (*str_end != '\0') + { + fprintf(stderr, "Configuration error: %s contains not number symbols\n", str); + return false; + } + + return true; +} diff --git a/profiler/profiler/src/config/commonconfigconversions.h b/profiler/profiler/src/config/commonconfigconversions.h new file mode 100644 index 0000000..2dcd7ef --- /dev/null +++ b/profiler/profiler/src/config/commonconfigconversions.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _COMMON_CONFIG_CONVERSIONS_H_ +#define _COMMON_CONFIG_CONVERSIONS_H_ + +#include "commonconfig.h" + +template<> +bool convert(const char *str, bool& value); + +template<> +bool convert(const char *str, unsigned long& value); + +#endif // _COMMON_CONFIG_CONVERSIONS_H_ diff --git a/profiler/profiler/src/config/configurationmanager.cpp b/profiler/profiler/src/config/configurationmanager.cpp new file mode 100644 index 0000000..3b8f4c0 --- /dev/null +++ b/profiler/profiler/src/config/configurationmanager.cpp @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <stdexcept> +#include <sstream> +#include <stdlib.h> + +#include "commonconfig.h" +#include "commonconfigconversions.h" +#include "configurationmanager.h" + +ConfigurationManager::ConfigurationManager() + : m_fileConfigProvider() + , m_environmentConfigProvider() +{ + const char *config_filename = getenv("PROF_CONFIG_FILENAME"); + if (config_filename) + { + try + { + m_fileConfigProvider.reset(new FileConfigProvider(config_filename)); + } + catch (std::exception& e) + { + fprintf(stderr, "%s: %s\n", config_filename, e.what()); + } + } + + m_environmentConfigProvider.reset(new EnvironmentConfigProvider()); +} + +template<typename T> +bool ConfigurationManager::FetchValue(const std::string &name, T &value) const +{ + std::string str_value; + + bool from_file = false; + if (m_fileConfigProvider) + { + from_file = m_fileConfigProvider->FetchValue(name, str_value); + } + + bool from_env = m_environmentConfigProvider->FetchValue(name, str_value); + if (from_file && from_env) + { + fprintf(stderr, "Configuration variable %s was overrided by environment\n", name.c_str()); + } + + if (from_file || from_env) + { + return convert<T>(str_value.c_str(), value); + } + else + { + return false; + } +} + +void ConfigurationManager::FetchConfig(ProfilerConfig &config) const +{ + // Save current configuration to temporary. + ProfilerConfig new_config(config); + + // + // We don't check whether the environment variables override the + // configuration or not. + // + + FetchValue("HEAPTRACK_SAMPLING_ENABLE", new_config.samplingEnabled); + if (new_config.samplingEnabled) + { + FetchValue("HEAPTRACK_SAMPLING_INTERVAL", new_config.samplingInterval); + FetchValue("HEAPTRACK_SAMPLING_RANDOMIZATION", new_config.samplingIntervalRandomization); + } + + // Apply changes to the current configuration. + config = new_config; +} + +template<typename T> +T ConfigurationManager::FetchGenericConfig() const +{ + T config; + + FetchConfig(config); + config.Validate(); + auto warnings = config.Verify(); + std::string warn; + if (!warnings.empty()) + { + warn = "Some errors detected in profiler configuration:"; + for (const auto &warning : warnings) + { + warn += "\n\t\t" + warning; + } + fprintf(stderr, "%s\n", warn.c_str()); + } + + return config; +} + +ProfilerConfig ConfigurationManager::FetchProfilerConfig() const +{ + return FetchGenericConfig<ProfilerConfig>(); +} diff --git a/profiler/profiler/src/config/configurationmanager.h b/profiler/profiler/src/config/configurationmanager.h new file mode 100644 index 0000000..0252231 --- /dev/null +++ b/profiler/profiler/src/config/configurationmanager.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _CONFIGURATION_MANAGER_H_ +#define _CONFIGURATION_MANAGER_H_ + +#include <string> +#include <memory> + +#include "profilerconfig.h" +#include "fileconfigprovider.h" +#include "environmentconfigprovider.h" + +class ConfigurationManager +{ +public: + ConfigurationManager(); + +private: + // Internal template method that takes name of the configuration variable + // and tries to fetch it from file than from environment and convert it to + // type T. + // + // FetchValue() will log info message if some configuration variable from + // file overrided by environment. + // + // FetchValue() will return true on success convertion or false if specified + // variable is not presented. + template<typename T> + bool FetchValue(const std::string &name, T &value) const; + + // + // FetchConfig() overrides the configuration with values fetched with + // FetchValue(). Other values are not changed. + // + + void FetchConfig(ProfilerConfig &config) const; + + // Get configuration for config type T from the Global Area. + template<typename T> + T FetchGenericConfig() const; + +public: + // Get configuration from the Global Area. + ProfilerConfig FetchProfilerConfig() const; + +private: + std::unique_ptr<FileConfigProvider> m_fileConfigProvider; + std::unique_ptr<EnvironmentConfigProvider> m_environmentConfigProvider; +}; + +#endif // _CONFIGURATION_MANAGER_H_ diff --git a/profiler/profiler/src/config/environmentconfigprovider.cpp b/profiler/profiler/src/config/environmentconfigprovider.cpp new file mode 100644 index 0000000..292f562 --- /dev/null +++ b/profiler/profiler/src/config/environmentconfigprovider.cpp @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <stdlib.h> + +#include "environmentconfigprovider.h" + +bool EnvironmentConfigProvider::FetchValue( + const std::string &name, std::string &value) const +{ + const char *env_str = getenv(name.c_str()); + if (env_str) + { + value = env_str; + } + + return env_str != nullptr; +} diff --git a/profiler/profiler/src/config/environmentconfigprovider.h b/profiler/profiler/src/config/environmentconfigprovider.h new file mode 100644 index 0000000..b6bde01 --- /dev/null +++ b/profiler/profiler/src/config/environmentconfigprovider.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _ENVIRONMENT_CONFIG_PROVIDER_H_ +#define _ENVIRONMENT_CONFIG_PROVIDER_H_ + +#include <string> + +class EnvironmentConfigProvider +{ +public: + // FetchValue() will return false if specified variable is not presented. + // Otherwise returns true. + bool FetchValue(const std::string &name, std::string &value) const; +}; + +#endif // _ENVIRONMENT_CONFIG_PROVIDER_H_ diff --git a/profiler/profiler/src/config/fileconfigprovider.cpp b/profiler/profiler/src/config/fileconfigprovider.cpp new file mode 100644 index 0000000..e9fb244 --- /dev/null +++ b/profiler/profiler/src/config/fileconfigprovider.cpp @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <iostream> +#include <fstream> +#include <system_error> +#include <stdexcept> + +#include <assert.h> +#include <errno.h> +#include <ctype.h> + +#include "fileconfigprovider.h" + +FileConfigProvider::FileConfigProvider(const std::string &filename) + : m_data() +{ + std::ifstream stream; + stream.exceptions(std::ios::badbit); + stream.open(filename, std::ios::in); + + std::string line; + while (std::getline(stream, line)) + { + std::string name; + std::string value; + bool is_name = true; + auto parse_error = std::runtime_error( + "Can't parse config file (syntax error)" + ); + + if (line[0] == '=') + { + throw parse_error; + } + + if (line.empty()) + { + continue; + } + + for (char c : line) + { + if (is_name) + { + if (c == '_' || isalnum(c)) + { + name.push_back(c); + } + else if (c == '=') + { + is_name = false; + } + else + { + throw parse_error; + } + } + else + { + value.push_back(c); + } + } + + if (is_name) + { + throw parse_error; + } + + m_data[name] = value; + } + + if (!stream.eof()) + { + assert(stream.fail()); + + if (errno) + { + throw std::system_error( + errno, std::system_category(), + "Can't parse config file" + ); + } + else + { + throw std::runtime_error( + "Can't parse config file (unknown error)" + ); + } + } +} + +bool FileConfigProvider::FetchValue( + const std::string &name, std::string &value) +{ + auto it = m_data.find(name); + if (it != m_data.end()) + { + auto ¶m_name = it->first; + auto ¶m_value = it->second; + + value = param_value; + + return true; + } + + return false; +} diff --git a/profiler/profiler/src/config/fileconfigprovider.h b/profiler/profiler/src/config/fileconfigprovider.h new file mode 100644 index 0000000..2484e65 --- /dev/null +++ b/profiler/profiler/src/config/fileconfigprovider.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _FILE_CONFIG_PROVIDER_H_ +#define _FILE_CONFIG_PROVIDER_H_ + +#include <string> +#include <unordered_map> +#include <utility> + +class FileConfigProvider +{ +public: + FileConfigProvider(const std::string &filename); + + // FetchValue() will return false if specified variable is not presented. + // Otherwise returns true. + bool FetchValue(const std::string &name, std::string &value); + +private: + std::unordered_map< + std::string, // Name of parameter. + std::string // Value of parameter. + > m_data; +}; + +#endif // _FILE_CONFIG_PROVIDER_H_ diff --git a/profiler/profiler/src/config/profilerconfig.cpp b/profiler/profiler/src/config/profilerconfig.cpp new file mode 100644 index 0000000..f5148f4 --- /dev/null +++ b/profiler/profiler/src/config/profilerconfig.cpp @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <assert.h> + +#include "commonconfig.h" +#include "profilerconfig.h" + +// +// Configuration parameters should be assigned to its defaults here. +// +// by default sampling is disabled +// by default sampling randomization is enabled +// default sampling interval is 512 byte (this is also mean interval in case of enabled randomization) +ProfilerConfig::ProfilerConfig() + : samplingEnabled(false) + , samplingIntervalRandomization(true) + , samplingInterval(512) +{} + +void ProfilerConfig::Validate() +{ + if (samplingEnabled) + { + if (samplingInterval == 0) + { + fprintf(stderr, "Sampling interval should be non-zero\n"); + } + } +} + +std::vector<std::string> ProfilerConfig::Verify() +{ + std::vector<std::string> warnings; + + if (!samplingEnabled) + { + // Sampling specific options verification. + + if (samplingInterval != 0) + { + warnings.push_back( + "sampling interval specification requires sampling enabled"); + } + + } + return warnings; +} diff --git a/profiler/profiler/src/config/profilerconfig.h b/profiler/profiler/src/config/profilerconfig.h new file mode 100644 index 0000000..67aa1a9 --- /dev/null +++ b/profiler/profiler/src/config/profilerconfig.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _PROFILER_CONFIG_H_ +#define _PROFILER_CONFIG_H_ + +#include <vector> +#include <string> + +// +// The ProfilerConfig structure describes configuration of the Profiler. +// +// NOTE: structure of the configuration can be changed when appropriate logic +// will be implemented. +// + +struct ProfilerConfig +{ + // Creates configuration with default values. + ProfilerConfig(); + + // + // Sampling features. + // + + bool samplingEnabled; + bool samplingIntervalRandomization; + unsigned long samplingInterval; + + // + // Validation and verification. + // + + void Validate(); + + std::vector<std::string> Verify(); +}; + +#endif // _PROFILER_CONFIG_H_ diff --git a/profiler/profiler/src/profiler.cpp b/profiler/profiler/src/profiler.cpp index e880f45..80d17ae 100644 --- a/profiler/profiler/src/profiler.cpp +++ b/profiler/profiler/src/profiler.cpp @@ -4,6 +4,7 @@ #include "pal_excerpts.h" #include "classfactory.h" #include "stackentry.h" +#include "config/configurationmanager.h" #include <new> #include <random> #include <string> @@ -125,12 +126,6 @@ public: // distance to next sample in bytes (value <= 0 means that it's time to take a sample) static __thread intptr_t g_distanceToNextSample = 0; -// by default sampling is disabled -static bool g_samplingEnabled = false; -// default sampling interval is 512 byte (this is also mean interval in case of enabled randomization) -static intptr_t g_samplingInterval = 512; -// by default sampling randomization is enabled -static bool g_samplingIntervalRandomization = true; // random number generator with values uniformly distributed on the [0.0,1.0) interval static thread_local UniformRandomGenerator<double> randgen(0.0, 1.0); @@ -357,26 +352,8 @@ HRESULT STDMETHODCALLTYPE Profiler::Initialize(IUnknown *pICorProfilerInfoUnk) { } PAL_Initialize(0, nullptr); - char *env = getenv("HEAPTRACK_SAMPLING_ENABLE"); - if (env) - { - g_samplingEnabled = bool(std::stoi(std::string(env))); - } - - if (g_samplingEnabled) - { - env = getenv("HEAPTRACK_SAMPLING_RANDOMIZATION"); - if (env) - { - g_samplingIntervalRandomization = bool(std::stoi(std::string(env))); - } - - env = getenv("HEAPTRACK_SAMPLING_INTERVAL"); - if (env) - { - g_samplingInterval = std::stoi(std::string(env)); - } - } + ConfigurationManager cm; + m_profilerConfig = cm.FetchProfilerConfig(); return S_OK; } @@ -677,13 +654,13 @@ HRESULT STDMETHODCALLTYPE // TODO: consider ignoring sampling for large allocations fully. // // Such cutoff should not introduce significant gap in probability of sampling (see more details on sampling probability below). - // For example, if we choose to return size of allocation directly if it's larger than g_samplingInterval, then - // we'll have 100% probability for all allocaitons > g_samplingInterval and just 63% probability for allocation equal to g_samplingInterval. + // For example, if we choose to return size of allocation directly if it's larger than m_profilerConfig.samplingInterval, then + // we'll have 100% probability for all allocaitons > m_profilerConfig.samplingInterval and just 63% probability for allocation equal to m_profilerConfig.samplingInterval. // // Intead, when P( sample in allocation of size x ) >= 99.9% condition is used, gap is small, and - // such condition is achieved for allocations with size somewhere around 6.9*g_samplingInterval. + // such condition is achieved for allocations with size somewhere around 6.9*m_profilerConfig.samplingInterval. - if (g_samplingEnabled) { + if (m_profilerConfig.samplingEnabled) { // Accumulated amount of bytes is calculated for each thread separately. // This doesn't seem to be an issue, because the only difference is that // instead of placing points (using Poisson Point Process) on line segment @@ -696,23 +673,23 @@ HRESULT STDMETHODCALLTYPE return S_OK; } - intptr_t samples = - g_distanceToNextSample / g_samplingInterval; - g_distanceToNextSample %= g_samplingInterval; + intptr_t samples = - g_distanceToNextSample / m_profilerConfig.samplingInterval; + g_distanceToNextSample %= m_profilerConfig.samplingInterval; do { - intptr_t nextSamplingInterval = g_samplingInterval; - if (g_samplingIntervalRandomization) { + intptr_t nextSamplingInterval = m_profilerConfig.samplingInterval; + if (m_profilerConfig.samplingIntervalRandomization) { // Poisson Point Process is used for randomization of points on line segment (https://en.wikipedia.org/wiki/Poisson_point_process). // Using it we'll place points randomly on line with all allocations, so that more points get to larger allocations // and less points get to smaller allocations. This randomization is needed for cases when there are lots of small - // allocations, which might be stepped over with constant sampling interval g_samplingInterval. + // allocations, which might be stepped over with constant sampling interval m_profilerConfig.samplingInterval. // // Probability of "k" points on "(a,b]" line segment is calculated using next formula: // P( N(a,b]=k ) = ( (lambda*(b-a))^k / (k!) ) * exp^(-lambda * (b-a)) // // Here: // 1) "N(a,b]" is the number of points on "(a,b]" line segment - // 2) "lambda" is the average number of points per some unit of extent such as length (in other words "1/g_samplingInterval") + // 2) "lambda" is the average number of points per some unit of extent such as length (in other words "1/m_profilerConfig.samplingInterval") // 3) "P( N(a,b]=k )" is random probability, and we can use random number generator to get it // // Since we need to find the next point, this means that we want to find such a line segment "(a,b]" where there're no points, i.e. k=0. @@ -723,13 +700,13 @@ HRESULT STDMETHODCALLTYPE // (b-a) = - (log(P( N(a,b]=0 ))) / lambda double probability = randgen.get(); - nextSamplingInterval = uintptr_t(- std::log(probability) * g_samplingInterval); + nextSamplingInterval = uintptr_t(- std::log(probability) * m_profilerConfig.samplingInterval); // TODO: consider limiting max value of next sampling interval // // To reduce size of gaps between samples, we can set upper limit for sampling interval. - // 25*g_samplingInterval seems reasonable, because probability of not getting a sample in 25*g_samplingInteval is - // 1 - P( sample in allocation of size 25*g_samplingInterval ), which is around 1.4*10^(-11) (i.e. very small). + // 25*m_profilerConfig.samplingInterval seems reasonable, because probability of not getting a sample in 25*g_samplingInteval is + // 1 - P( sample in allocation of size 25*m_profilerConfig.samplingInterval ), which is around 1.4*10^(-11) (i.e. very small). // Such cutoff won't interfere with distribution much. @@ -765,7 +742,7 @@ HRESULT STDMETHODCALLTYPE } while (g_distanceToNextSample <= 0); - reportedSize = samples * g_samplingInterval; + reportedSize = samples * m_profilerConfig.samplingInterval; } ClearShadowStack(); diff --git a/profiler/profiler/src/profiler.h b/profiler/profiler/src/profiler.h index 497fac5..9521476 100644 --- a/profiler/profiler/src/profiler.h +++ b/profiler/profiler/src/profiler.h @@ -7,6 +7,8 @@ #include <cor.h> #include <corprof.h> +#include "config/profilerconfig.h" + class Profiler : public ICorProfilerCallback3 { public: Profiler(); @@ -188,6 +190,7 @@ public: private: LONG m_referenceCount; ICorProfilerInfo3 *info; + ProfilerConfig m_profilerConfig; }; #endif // PROFILER_H |