26#ifndef TIMEMORY_MANAGER_MANAGER_CPP_
27#define TIMEMORY_MANAGER_MANAGER_CPP_ 1
31#include "timemory/backends/process.hpp"
46#if defined(TIMEMORY_MANAGER_SOURCE) || defined(TIMEMORY_MANAGER_INLINE)
51# include "timemory/backends/cpu.hpp"
52# include "timemory/backends/threading.hpp"
58# include "timemory/version.h"
82: m_instance_count(f_manager_instance_count()++)
84, m_thread_index(threading::get_id())
85, m_thread_id(std::this_thread::get_id())
86, m_lock(std::make_shared<auto_lock_t>(m_mutex, std::defer_lock))
92 static bool _once = [=] {
97 auto _cpu_info = cpu::get_info();
98 auto _user = get_env<std::string>(
"USER",
"nobody");
100 for(
auto&& itr : {
"SHELL",
"HOME",
"PWD" })
102 auto _var = get_env<std::string>(itr,
"");
104 add_metadata(itr, _var);
107 add_metadata(
"USER", _user);
108 add_metadata(
"LAUNCH_DATE", _launch_date);
109 add_metadata(
"LAUNCH_TIME", _launch_time);
110 add_metadata(
"TIMEMORY_API", demangle<TIMEMORY_API>());
112# if defined(TIMEMORY_VERSION_STRING)
113 add_metadata(
"TIMEMORY_VERSION", TIMEMORY_VERSION_STRING);
116# if defined(TIMEMORY_GIT_DESCRIBE)
117 add_metadata(
"TIMEMORY_GIT_DESCRIBE", TIMEMORY_GIT_DESCRIBE);
120# if defined(TIMEMORY_GIT_REVISION)
121 add_metadata(
"TIMEMORY_GIT_REVISION", TIMEMORY_GIT_REVISION);
124 add_metadata(
"CPU_MODEL", _cpu_info.model);
125 add_metadata(
"CPU_VENDOR", _cpu_info.vendor);
126 add_metadata(
"CPU_FEATURES", _cpu_info.features);
127 add_metadata(
"CPU_FREQUENCY", _cpu_info.frequency);
128 add_metadata(
"HW_CONCURRENCY", threading::affinity::hw_concurrency());
129 add_metadata(
"HW_PHYSICAL_CPU", threading::affinity::hw_physicalcpu());
131 for(
int i = 0; i < 3; ++i)
134 std::stringstream _cache_lvl;
135 _cache_lvl <<
"HW_L" << (i + 1) <<
"_CACHE_SIZE";
136 add_metadata(_cache_lvl.str(), _cache_size);
139# if !defined(TIMEMORY_DISABLE_BANNER)
140 if(m_settings->get_banner())
141 printf(
"#------------------------- tim::manager initialized "
142 "[pid=%i] -------------------------#\n",
147 f_manager_persistent_data().metadata_count = 0;
153 threading::affinity::set();
155 if(m_settings && m_settings->get_initialized())
164 auto _remain = --f_manager_instance_count();
165 bool _last = (get_shared_ptr_pair<this_type, TIMEMORY_API>().second ==
nullptr ||
166 _remain == 0 || m_instance_count == 0);
170 f_thread_counter().store(0, std::memory_order_relaxed);
173# if !defined(TIMEMORY_DISABLE_BANNER)
174 if(_last && m_settings && m_settings->get_banner())
176 printf(
"#---------------------- tim::manager destroyed "
178 "----------------------#\n",
179 m_rank, process::get_id());
192 auto _cleanup = [&](
auto& _functors) {
193 auto _orig = _functors.size();
194 auto itr = _functors.begin();
195 for(; itr != _functors.end(); ++itr)
197 if(itr->first == key)
201 if(itr != _functors.end())
204 _functors.erase(itr);
208 PRINT_HERE(
"%s [size: %i]",
"cleaned", (
int) (_orig - _functors.size()));
211 _cleanup(m_finalizer_cleanups);
219 m_is_finalizing =
true;
220 auto _orig_sz = m_finalizer_cleanups.size();
224 PRINT_HERE(
"%s [size: %i]",
"cleaning", (
int) m_finalizer_cleanups.size());
229 std::reverse(_functors.begin(), _functors.end());
231 for(
auto& itr : _functors)
237 _cleanup(m_finalizer_cleanups);
242 (
int) (_orig_sz - m_finalizer_cleanups.size()));
253 m_is_initialized =
true;
254 bool _owns = m_lock->owns_lock();
257 m_initializers.erase(std::remove_if(m_initializers.begin(), m_initializers.end(),
258 [](
auto& itr) { return itr(); }),
259 m_initializers.end());
269 auto _print_size = [&](
const char* _msg) {
272 auto _get_sz = [](
auto& _mdata) {
274 for(
auto& itr : _mdata)
275 _val += itr.second.size();
278 PRINT_HERE(
"%s [master: %i/%i, worker: %i/%i, other: %i]", _msg,
279 _get_sz(m_master_cleanup), _get_sz(m_master_finalizers),
280 _get_sz(m_worker_cleanup), _get_sz(m_worker_finalizers),
281 (
int) m_pointer_fini.size());
286 for(
auto& _functors : _pdata)
289 std::reverse(_functors.second.begin(), _functors.second.end());
291 for(
auto& itr : _functors.second)
294 _functors.second.clear();
298 m_is_finalizing =
true;
299 m_rank = std::max<int32_t>(m_rank, dmp::rank());
301 _print_size(
"finalizing");
305 _print_size(
"finalizing (pre-storage-cleanup)");
312 _finalize(m_worker_cleanup);
314 _finalize(m_master_cleanup);
316 _print_size(
"finalizing (pre-storage-finalization)");
322 _finalize(m_worker_finalizers);
324 _finalize(m_master_finalizers);
326 _print_size(
"finalizing (pre-pointer-finalization)");
328 for(
auto& itr : m_pointer_fini)
331 m_pointer_fini.clear();
333 m_is_finalizing =
false;
335 _print_size(
"finalized");
337 if(m_instance_count == 0 && m_rank == 0)
343 m_is_finalized =
true;
354 if(!manager::f_use_exit_hook())
359 auto master_count = f_manager_instance_count().load();
362 auto master_manager =
363 get_shared_ptr_pair_main_instance<manager, TIMEMORY_API>();
366 master_manager->internal_write_metadata(
"manager::exit_hook");
367 master_manager.reset();
382 m_rank = std::max<int32_t>(m_rank, dmp::rank());
383 if(m_write_metadata < 0)
388 auto _outp_prefix =
_settings->get_global_output_prefix();
389 m_metadata_prefix = _outp_prefix;
391 PRINT_HERE(
"[rank=%i][id=%i] metadata prefix: '%s'", m_rank, m_instance_count,
392 m_metadata_prefix.c_str());
400 auto_lock_t _lk(type_mutex<manager>(), std::defer_lock);
408 using policy_type = policy::output_archive_t<manager>;
410 oa->setNextName(
"timemory");
413 oa->setNextName(
"metadata");
417 auto& _info_metadata = f_manager_persistent_data().info_metadata;
418 auto& _func_metadata = f_manager_persistent_data().func_metadata;
419 oa->setNextName(
"info");
421 for(
const auto& itr : _info_metadata)
422 (*oa)(cereal::make_nvp(itr.first.c_str(), itr.second));
423 for(
const auto& itr : _func_metadata)
424 itr(
static_cast<void*
>(oa.get()));
434 oa->setNextName(
"output");
436 for(
const auto& itr : m_output_files)
437 (*oa)(cereal::make_nvp(itr.first.c_str(), itr.second));
459 PRINT_HERE(
"[%s]> metadata disabled for rank %i", context, (
int) m_rank);
463 if(tim::get_env<bool>(
"TIMEMORY_CXX_PLOT_MODE",
false))
466 PRINT_HERE(
"[%s]> plot mode enabled. Skipping metadata", context);
478 auto_lock_t _lk{ type_mutex<manager>(), std::defer_lock };
482 std::map<std::string, std::set<size_t>> _hashes{};
483 if(m_hash_ids && m_hash_aliases)
485 for(
const auto& itr : (*m_hash_aliases))
487 auto hitr = m_hash_ids->find(itr.second);
488 if(hitr != m_hash_ids->end())
490 _hashes[operation::decode<TIMEMORY_API>{}(hitr->second)].
insert(
492 _hashes[operation::decode<TIMEMORY_API>{}(hitr->second)].
insert(
496 for(
const auto& itr : (*m_hash_ids))
497 _hashes[operation::decode<TIMEMORY_API>{}(itr.second)].
insert(itr.first);
502 if(_hashes.empty() && m_write_metadata < 1 &&
503 f_manager_persistent_data().metadata_count == 0)
506 if((f_verbose() >= 0 || _banner || f_debug()) && !_hashes.empty())
507 printf(
"\n[metadata::%s]> Outputting '%s' and '%s'...\n", context, fname.c_str(),
509 else if((f_verbose() >= 0 || _banner || f_debug()) && _hashes.empty())
510 printf(
"\n[metadata::%s]> Outputting '%s'...\n", context, fname.c_str());
520 printf(
"[manager]> Warning! Error opening '%s'...\n", fname.c_str());
530 using policy_type = policy::output_archive_t<manager>;
532 oa->setNextName(
"timemory");
535 oa->setNextName(
"functions");
539 for(
const auto& itr : _hashes)
540 (*oa)(cereal::make_nvp(itr.first.c_str(), itr.second));
550 printf(
"[manager]> Warning! Error opening '%s'...\n", hname.c_str());
563 PRINT_HERE(
"[%s]> metadata disabled for rank %i", context, (
int) m_rank);
567 if(m_num_entries < 1 && m_write_metadata < 1)
570 PRINT_HERE(
"[%s]> No components generated output. Skipping metadata",
575 if(tim::get_env<bool>(
"TIMEMORY_CXX_PLOT_MODE",
false))
578 PRINT_HERE(
"[%s]> plot mode enabled. Skipping metadata", context);
585 PRINT_HERE(
"[%s]> Null pointer to settings", context);
589 bool _auto_output =
_settings->get_auto_output();
590 bool _file_output =
_settings->get_file_output();
591 auto _outp_prefix =
_settings->get_global_output_prefix();
593 static bool written =
false;
594 if(written || m_write_metadata < 1)
596 if(f_debug() && written)
597 PRINT_HERE(
"[%s]> metadata already written", context);
598 if(f_debug() && m_write_metadata < 1)
599 PRINT_HERE(
"[%s]> metadata disabled: %i", context, (
int) m_write_metadata);
603 if((!_auto_output || !_file_output) && m_write_metadata < 1)
605 if(f_debug() && !_auto_output)
606 PRINT_HERE(
"[%s]> metadata disabled because auto output disabled", context);
607 if(f_debug() && !_file_output)
608 PRINT_HERE(
"[%s]> metadata disabled because file output disabled", context);
613 m_write_metadata = -1;
616 PRINT_HERE(
"metadata prefix: '%s'", m_metadata_prefix.c_str());
619 if(m_metadata_prefix.empty())
620 m_metadata_prefix = _outp_prefix;
623 PRINT_HERE(
"metadata prefix: '%s'", m_metadata_prefix.c_str());
626 auto only_ascii = [](
char c) {
return isascii(c) == 0; };
627 m_metadata_prefix.erase(
628 std::remove_if(m_metadata_prefix.begin(), m_metadata_prefix.end(), only_ascii),
629 m_metadata_prefix.end());
632 PRINT_HERE(
"metadata prefix: '%s'", m_metadata_prefix.c_str());
635 if(m_metadata_prefix.empty())
636 m_metadata_prefix =
"timemory-output/";
639 PRINT_HERE(
"metadata prefix: '%s'", m_metadata_prefix.c_str());
643 if(std::iscntrl(m_metadata_prefix[0], _lc))
644 m_metadata_prefix =
"timemory-output/";
647 PRINT_HERE(
"metadata prefix: '%s'", m_metadata_prefix.c_str());
658 m_output_files[_category][_label].insert(
_file);
685 if(m_pointer_fini.find(_key) != m_pointer_fini.end())
686 m_pointer_fini.erase(_key);
695 for(
auto itr = _functors.begin(); itr != _functors.end(); ++itr)
697 if(itr->first == _key)
699 _functors.erase(itr);
705 _remove_functor(m_finalizer_cleanups);
714 for(
auto& _functors : _pdata)
716 for(
auto itr = _functors.second.begin(); itr != _functors.second.end(); ++itr)
718 if(itr->first == _key)
720 _functors.second.erase(itr);
727 _remove_finalizer(m_master_cleanup);
728 _remove_finalizer(m_worker_cleanup);
729 _remove_finalizer(m_master_finalizers);
730 _remove_finalizer(m_worker_finalizers);
739 ++f_manager_persistent_data().metadata_count;
740 f_manager_persistent_data().info_metadata.insert({ _key,
std::string{ _value } });
749 ++f_manager_persistent_data().metadata_count;
750 f_manager_persistent_data().info_metadata.insert({ _key, _value });
757 std::function<
void()> _func)
760 m_synchronize[_key].emplace(_id, std::move(_func));
770 if(m_synchronize[_key].find(_id) != m_synchronize[_key].
end())
771 m_synchronize[_key].erase(_id);
780 for(
auto& itr : m_synchronize)
782 for(
auto& fitr : itr.second)
839manager::f_manager_persistent_data()
841 static persistent_data _instance{};
852 static thread_local auto _inst =
853 get_shared_ptr_pair_instance<manager, TIMEMORY_API>();
864 static auto _pinst = get_shared_ptr_pair_main_instance<manager, TIMEMORY_API>();
865 manager::f_manager_persistent_data().master_instance = _pinst;
884 static auto _pinst = tim::get_shared_ptr_pair<manager, TIMEMORY_API>();
886 return _pinst.first.get();
894 static auto _preloaded = []() {
895 auto library_ctor = tim::get_env<bool>(
"TIMEMORY_LIBRARY_CTOR",
true);
899 auto ld_preload = tim::get_env<std::string>(
"LD_PRELOAD",
"",
false);
900 auto dyld_preload = tim::get_env<std::string>(
"DYLD_INSERT_LIBRARIES",
"",
false);
901 std::regex lib_regex(
"libtimemory");
902 if(std::regex_search(ld_preload, lib_regex) ||
903 std::regex_search(dyld_preload, lib_regex))
918 static thread_local bool _once =
false;
929 static auto _time_output =
_settings->get_time_output();
930 static auto _time_format =
_settings->get_time_format();
934 if(_debug || _verbose > 3)
935 printf(
"[%s]> initializing manager...\n", __FUNCTION__);
940 if(!_master && _inst)
941 _master.reset(_inst);
945 if(_worker == _master)
953 printf(
"[%s]> manager :: master != worker : %p vs. %p. TLS behavior is abnormal. "
954 "Report any issues to https://github.com/NERSC/timemory/issues\n",
955 __FUNCTION__, (
void*) _master.get(), (
void*) _worker.get());
959 for(
const auto& itr : default_signals)
964 auto _exit_action = [=](
int nsig) {
967 std::cout <<
"Finalizing after signal: " << nsig <<
" :: "
994#if defined(TIMEMORY_MANAGER_SOURCE)
static void serialize_environment(Archive &ar)
void add_file_output(const string_t &_category, const string_t &_label, const string_t &_file)
std::deque< finalizer_pair_t > finalizer_list_t
void synchronize()
Synchronizes thread-data for storage.
std::unique_lock< mutex_t > auto_lock_t
static void add_metadata(const std::string &, const Tp &)
Add a metadata entry of a non-string type. If this fails to serialize, either include either the appr...
void remove_cleanup(void *)
remove a cleanup functor
void remove_synchronization(const std::string &, int64_t)
Remove function for synchronizing data in threads.
static pointer_t instance()
Get a shared pointer to the instance for the current thread.
void add_text_output(const string_t &_label, const string_t &_file)
static pointer_t master_instance()
Get a shared pointer to the instance on the primary thread.
void add_json_output(const string_t &_label, const string_t &_file)
std::map< int32_t, finalizer_list_t > finalizer_pmap_t
std::shared_ptr< this_type > pointer_t
static void set_persistent_master(pointer_t _pinst)
This function stores the primary manager instance for the application.
void update_metadata_prefix()
Updates settings, rank, output prefix, etc.
static void exit_hook()
The exit hook function.
static bool get_is_main_thread()
Return whether this is the main thread.
void internal_write_metadata(const char *="")
void write_metadata(const std::string &, const char *="")
Print metadata to filename.
void remove_finalizer(const std::string &)
remove a finalizer functor
void add_synchronization(const std::string &, int64_t, std::function< void()>)
Add function for synchronizing data in threads.
static std::string str(const sys_signal &)
static void enable(const sys_signal &)
static signal_set_t get_enabled()
static void set_exit_action(signal_function_t _f)
static signal_set_t get_default()
#define TIMEMORY_MANAGER_LINKAGE(...)
#define TIMEMORY_MANAGER_LINKAGE_API
bool open(std::ofstream &_ofs, std::string _fpath, Args &&... _args)
hash_alias_ptr_t & get_hash_aliases()
hash_map_ptr_t & get_hash_ids()
_reported insert(_hash_id)
const string_t const string_t & _dir
char const std::string & _prefix
void set_env(const std::string &env_var, const Tp &_val, int override)
std::unique_lock< mutex_t > auto_lock_t
Unique lock type around mutex_t.
TIMEMORY_SETTINGS_INLINE std::string get_local_datetime(const char *dt_format, std::time_t *dt_curr)
bool enable_signal_detection(signal_settings::signal_set_t=signal_settings::get_default())
void initialize(CompList< CompTypes... > &obj, std::initializer_list< EnumT > components)
char argparse::argument_parser tim::settings * _settings
tim::mpl::apply< std::string > string
void timemory_library_constructor()
manager * timemory_manager_master_instance()
auto get(const auto_bundle< Tag, Types... > &_obj)
void consume_parameters(ArgsT &&...)
arg_result get(size_t _idx, Tp &_value)
static notes_ptr_t & get_notes()
static pointer_t shared_instance()
static string_t compose_output_filename(string_t _tag, string_t _ext, bool _use_suffix=use_output_suffix(), int32_t _suffix=default_process_suffix(), bool _make_dir=false, std::string _explicit={})
static std::time_t * get_launch_time(Tag={})
static void serialize_settings(Archive &)