timemory 3.3.0
Modular C++ Toolkit for Performance Analysis and Logging. Profiling API and Tools for C, C++, CUDA, Fortran, and Python. The C++ template API is essentially a framework to creating tools: it is designed to provide a unifying interface for recording various performance measurements alongside data logging and interfaces to other tools.
definition.hpp
Go to the documentation of this file.
1// MIT License
2//
3// Copyright (c) 2020, The Regents of the University of California,
4// through Lawrence Berkeley National Laboratory (subject to receipt of any
5// required approvals from the U.S. Dept. of Energy). All rights reserved.
6//
7// Permission is hereby granted, free of charge, to any person obtaining a copy
8// of this software and associated documentation files (the "Software"), to deal
9// in the Software without restriction, including without limitation the rights
10// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11// copies of the Software, and to permit persons to whom the Software is
12// furnished to do so, subject to the following conditions:
13//
14// The above copyright notice and this permission notice shall be included in all
15// copies or substantial portions of the Software.
16//
17// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23// SOFTWARE.
24
25/**
26 * \file timemory/environment/definition.hpp
27 * \brief The definitions for the types in environment
28 */
29
30#pragma once
31
37
38#include <atomic>
39#include <iosfwd>
40#include <mutex>
41#include <regex>
42#include <sstream>
43#include <string>
44
45namespace tim
46{
47//
48//--------------------------------------------------------------------------------------//
49//
50#if !defined(TIMEMORY_USE_ENVIRONMENT_EXTERN)
51//
52//--------------------------------------------------------------------------------------//
53//
54// environment
55//
56//--------------------------------------------------------------------------------------//
57//
58// if passed a global, insert m_env into it's array
59//
60TIMEMORY_ENVIRONMENT_LINKAGE(env_settings::env_settings)
61(env_settings* _global, int _id)
62: m_id(_id)
63, m_env(new env_uomap_t)
64{
65 if(_global && _id != 0)
66 {
67 auto_lock_t lk(type_mutex<env_settings>(), std::defer_lock);
68 lock_flag().store(true);
69 if(!lk.owns_lock())
70 lk.lock();
71 _global->m_env_other.emplace_back(m_env);
72 lock_flag().store(false);
73 }
74}
75//
76//--------------------------------------------------------------------------------------//
77//
78// only the zero id deletes
79//
81{
82 if(m_id == 0)
83 {
84 delete m_env;
85 for(auto& itr : m_env_other)
86 delete itr;
87 }
88}
89//
90//--------------------------------------------------------------------------------------//
91//
94{
95 auto_lock_t lk(type_mutex<env_settings>(), std::defer_lock);
96 lock_flag().store(true);
97 if(!lk.owns_lock())
98 lk.lock();
99
100 auto _tmp = *m_env;
102 for(const auto& itr : _tmp)
103 _ret[itr.first] = itr.second;
104
105 lock_flag().store(false);
106 return _ret;
107}
108//
109//--------------------------------------------------------------------------------------//
110//
112env_settings::print(std::ostream& os, filter_func_t&& _filter) const
113{
114 if(m_id == 0)
115 const_cast<env_settings&>(*this).collapse();
116
117 auto _data = get();
118
119 size_t _wl = 35;
120 size_t _wr = 0;
121 size_t _count = 0;
122 for(const auto& itr : _data)
123 {
124 if(_filter(itr.first))
125 {
126 _wl = std::max<size_t>(itr.first.length(), _wl);
127 _wr = std::max<size_t>(itr.second.length(), _wr);
128 ++_count;
129 }
130 }
131
132 if(_count == 0)
133 return;
134
135 std::stringstream filler{};
136 filler.fill('-');
137 filler << '#';
138 {
139 std::stringstream _tmp{};
140 _tmp << " " << std::setw(_wl) << std::right << " "
141 << " = " << std::setw(_wr) << std::left << " "
142 << "\n";
143 filler << std::setw(_tmp.str().length() + 1) << "";
144 }
145 filler << '#';
146
147 std::stringstream ss;
148 ss << filler.str() << '\n';
149 ss << "# Environment settings:\n";
150 for(const auto& itr : _data)
151 {
152 if(_filter(itr.first))
153 {
154 ss << "# " << std::setw(_wl) << std::right << itr.first << " = "
155 << std::setw(_wr) << std::left << itr.second << '\n';
156 }
157 }
158 ss << filler.str();
159 os << ss.str() << '\n';
160}
161//
162//--------------------------------------------------------------------------------------//
163//
164// NOLINTNEXTLINE
166env_settings::collapse()
167{
168 if(m_id != 0)
169 return;
170
171 auto_lock_t lk(type_mutex<env_settings>(), std::defer_lock);
172 if(!lk.owns_lock())
173 lk.lock();
174
175 lock_flag().store(true);
176
177 // insert all the other maps into this map
178 for(size_t i = 0; i < m_env_other.size(); ++i)
179 {
180 // get the map instance
181 auto* itr = m_env_other[i];
182 if(itr)
183 {
184 // loop over entries
185 for(const auto& mitr : *m_env_other[i])
186 {
187 auto key = mitr.first;
188 if(m_env->find(key) != m_env->end())
189 {
190 // if the key already exists and if the entries differ,
191 // create a new unique entry for the index
192 if(m_env->find(key)->second != mitr.second)
193 {
194 key += string_t("[@") + std::to_string(i + 1) + string_t("]");
195 (*m_env)[key] = mitr.second;
196 }
197 }
198 else
199 {
200 // if a new entry, insert without unique tag to avoid duplication
201 // when thread count is very high
202 (*m_env)[key] = mitr.second;
203 }
204 }
205 }
206 }
207 lock_flag().store(false);
208}
209//
210//--------------------------------------------------------------------------------------//
211//
212// specialization for string since the above will have issues if string includes spaces
213//
214template <>
216get_env(const std::string& env_id, std::string _default, bool _store)
217{
218 if(env_id.empty())
219 return _default;
220
221 auto* _env_settings = env_settings::instance();
222 char* env_var = std::getenv(env_id.c_str());
223 if(env_var)
224 {
225 std::stringstream ss;
226 ss << env_var;
227 if(_env_settings && _store)
228 _env_settings->insert(env_id, ss.str());
229 return ss.str();
230 }
231 // record default value
232 if(_env_settings && _store)
233 _env_settings->insert(env_id, _default);
234
235 // return default if not specified in environment
236 return _default;
237}
238//
239//--------------------------------------------------------------------------------------//
240//
241// overload for boolean
242//
243template <>
245get_env(const std::string& env_id, bool _default, bool _store)
246{
247 if(env_id.empty())
248 return _default;
249
250 auto* _env_settings = env_settings::instance();
251 char* env_var = std::getenv(env_id.c_str());
252 if(env_var)
253 {
254 std::string var = std::string(env_var);
255 bool val = true;
256 if(var.find_first_not_of("0123456789") == std::string::npos)
257 {
258 val = (bool) atoi(var.c_str());
259 }
260 else
261 {
262 for(auto& itr : var)
263 itr = tolower(itr);
264 for(const auto& itr : { "off", "false", "no", "n", "f", "0" })
265 {
266 if(var == itr)
267 {
268 if(_env_settings && _store)
269 _env_settings->insert<bool>(env_id, false);
270 return false;
271 }
272 }
273 }
274 if(_env_settings && _store)
275 _env_settings->insert<bool>(env_id, val);
276 return val;
277 }
278 // record default value
279 if(_env_settings && _store)
280 _env_settings->insert<bool>(env_id, _default);
281
282 // return default if not specified in environment
283 return _default;
284}
285//
286//--------------------------------------------------------------------------------------//
287//
288// specialization for string since the above will have issues if string includes spaces
289//
290template <>
292load_env(const std::string& env_id, std::string _default)
293{
294 if(env_id.empty())
295 return _default;
296
297 auto* _env_settings = env_settings::instance();
298 auto itr = _env_settings->get(env_id);
299 if(itr != _env_settings->end())
300 return itr->second;
301
302 // return default if not specified in environment
303 return _default;
304}
305//
306//--------------------------------------------------------------------------------------//
307//
308// overload for boolean
309//
310template <>
312load_env(const std::string& env_id, bool _default)
313{
314 namespace regex_const = std::regex_constants;
315
316 if(env_id.empty())
317 return _default;
318
319 auto* _env_settings = env_settings::instance();
320 auto itr = _env_settings->get(env_id);
321 if(itr != _env_settings->end())
322 {
323 auto val = itr->second;
324 const auto regex_constants = regex_const::egrep | regex_const::icase;
325 const std::string pattern = "^(off|false|no|n|f|0)$";
326 bool _match = false;
327 try
328 {
329 _match = std::regex_match(val, std::regex(pattern, regex_constants));
330 } catch(std::bad_cast&)
331 {
332 for(auto& vitr : val)
333 vitr = tolower(vitr);
334 for(const auto& vitr : { "off", "false", "no", "n", "f", "0" })
335 {
336 if(val == vitr)
337 {
338 _match = true;
339 break;
340 }
341 }
342 }
343 return (_match) ? false : true;
344 }
345
346 // return default if not specified in environment
347 return _default;
348}
349//
350//--------------------------------------------------------------------------------------//
351//
353print_env(std::ostream& os) { os << (*env_settings::instance()); }
354//
355//--------------------------------------------------------------------------------------//
356//
359{
360 static std::atomic<int> _count{ 0 };
361 static env_settings _instance{};
362 static thread_local int _id = _count++;
363 static thread_local env_settings* _local =
364 (_id == 0) ? (&_instance) : new env_settings{ &_instance, _id };
365 static thread_local auto _ldtor = scope::destructor{ []() {
366 if(_local == &_instance || _id == 0)
367 return;
368 delete _local;
369 _local = nullptr;
370 } };
371 return _local;
372 (void) _ldtor;
373}
374//
375//--------------------------------------------------------------------------------------//
376//
377#endif // !defined(TIMEMORY_USE_ENVIRONMENT_EXTERN)
378//
379//--------------------------------------------------------------------------------------//
380//
381} // namespace tim
std::string string_t
Definition: declaration.hpp:57
std::map< string_t, string_t > env_map_t
Definition: declaration.hpp:58
static env_settings * instance()
void print(std::ostream &, filter_func_t &&_filter=[](const std::string &) { return true;}) const
env_map_t get() const
return false
Definition: definition.hpp:326
const hash_alias_ptr_t hash_value_t std::string *& _ret
Definition: definition.hpp:300
Definition: kokkosp.cpp:39
std::unique_lock< mutex_t > auto_lock_t
Unique lock type around mutex_t.
Definition: locking.hpp:42
void print_env(std::ostream &os, FuncT &&_filter)
Print all environment queries and their values which satisfy the filter conditions.
Tp get_env(const std::string &env_id, Tp _default, bool _store)
Tp load_env(const std::string &env_id, Tp _default)
tim::mpl::apply< std::string > string
Definition: macros.hpp:53
const std::string std::ostream * os
TIMEMORY_ENVIRONMENT_LINKAGE(env_settings::~env_settings())
Definition: definition.hpp:80
provides an object which can be returned from functions that will execute the lambda provided during ...
Definition: types.hpp:700