summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOleg Lekarev <o.lekarev@samsung.com>2023-05-24 18:44:51 +0300
committerGleb Balykov/Advanced System SW Lab /SRR/Staff Engineer/Samsung Electronics <g.balykov@samsung.com>2023-06-08 16:09:56 +0300
commit091a13118cd98b90022b48e682eb7b95e4b2d7df (patch)
treeecff470445982e7323365b3d20d1bfbe5e750d68
parentf5dbdb98a37d2fb7fe0a5ffc177958dea6233dfe (diff)
downloadheaptrack-091a13118cd98b90022b48e682eb7b95e4b2d7df.tar.gz
heaptrack-091a13118cd98b90022b48e682eb7b95e4b2d7df.tar.bz2
heaptrack-091a13118cd98b90022b48e682eb7b95e4b2d7df.zip
Configurator manager from file or environment added
-rw-r--r--profiler/profiler/src/CMakeLists.txt7
-rw-r--r--profiler/profiler/src/config/commonconfig.h23
-rw-r--r--profiler/profiler/src/config/commonconfigconversions.cpp88
-rw-r--r--profiler/profiler/src/config/commonconfigconversions.h28
-rw-r--r--profiler/profiler/src/config/configurationmanager.cpp118
-rw-r--r--profiler/profiler/src/config/configurationmanager.h65
-rw-r--r--profiler/profiler/src/config/environmentconfigprovider.cpp31
-rw-r--r--profiler/profiler/src/config/environmentconfigprovider.h30
-rw-r--r--profiler/profiler/src/config/fileconfigprovider.cpp121
-rw-r--r--profiler/profiler/src/config/fileconfigprovider.h40
-rw-r--r--profiler/profiler/src/config/profilerconfig.cpp61
-rw-r--r--profiler/profiler/src/config/profilerconfig.h52
-rw-r--r--profiler/profiler/src/profiler.cpp57
-rw-r--r--profiler/profiler/src/profiler.h3
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 &param_name = it->first;
+ auto &param_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