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.
trace.cpp File Reference
#include "timemory/trace.hpp"
#include "timemory/compat/library.h"
#include "timemory/library.h"
#include "timemory/runtime/configure.hpp"
#include "timemory/timemory.hpp"
#include "timemory/utility/bits/signals.hpp"
#include <cstdarg>
#include <cstdlib>
#include <deque>
#include <iostream>
#include <unordered_map>
+ Include dependency graph for trace.cpp:

Go to the source code of this file.

Macros

#define TIMEMORY_LIBRARY_SOURCE   1
 

Typedefs

using string_t = std::string
 
using overhead_map_t = std::unordered_map< size_t, std::pair< wall_clock, size_t > >
 
using throttle_set_t = std::set< size_t >
 
using traceset_t = tim::component_bundle< TIMEMORY_API, user_trace_bundle >
 
using trace_map_t = std::unordered_map< size_t, std::deque< traceset_t > >
 
using mpi_trace_bundle_t = tim::component_tuple<>
 

Functions

std::array< bool, 2 > & get_library_state ()
 
bool setup_mpi_gotcha ()
 
bool timemory_trace_is_initialized ()
 
bool timemory_is_throttled (const char *name)
 
void timemory_reset_throttle (const char *name)
 
void timemory_add_hash_id (uint64_t id, const char *name)
 
void timemory_add_hash_ids (uint64_t nentries, uint64_t *ids, const char **names)
 
void timemory_copy_hash_ids ()
 
void timemory_push_trace_hash (uint64_t id)
 
void timemory_pop_trace_hash (uint64_t id)
 
void timemory_push_trace (const char *name)
 
void timemory_pop_trace (const char *name)
 
void timemory_trace_set_env (const char *env_var, const char *env_val)
 
void timemory_trace_init (const char *comps, bool read_command_line, const char *cmd)
 
void timemory_trace_finalize (void)
 

Macro Definition Documentation

◆ TIMEMORY_LIBRARY_SOURCE

#define TIMEMORY_LIBRARY_SOURCE   1

Definition at line 26 of file trace.cpp.

Typedef Documentation

◆ mpi_trace_bundle_t

Definition at line 335 of file trace.cpp.

◆ overhead_map_t

using overhead_map_t = std::unordered_map<size_t, std::pair<wall_clock, size_t> >

Definition at line 50 of file trace.cpp.

◆ string_t

using string_t = std::string

Definition at line 49 of file trace.cpp.

◆ throttle_set_t

using throttle_set_t = std::set<size_t>

Definition at line 51 of file trace.cpp.

◆ trace_map_t

using trace_map_t = std::unordered_map<size_t, std::deque<traceset_t> >

Definition at line 53 of file trace.cpp.

◆ traceset_t

using traceset_t = tim::component_bundle<TIMEMORY_API, user_trace_bundle>

Definition at line 52 of file trace.cpp.

Function Documentation

◆ get_library_state()

std::array< bool, 2 > & get_library_state ( )

Definition at line 127 of file library.cpp.

128{
129 static auto _instance = std::array<bool, 2>({ { false, false } });
130 return _instance;
131}

Referenced by timemory_finalize_library(), timemory_init_library(), timemory_library_is_initialized(), timemory_pop_trace(), timemory_pop_trace_hash(), timemory_push_trace(), timemory_push_trace_hash(), timemory_trace_is_initialized(), and timemory_trace_set_env().

◆ setup_mpi_gotcha()

bool setup_mpi_gotcha ( )

Definition at line 340 of file trace.cpp.

341{
342 return false;
343}

◆ timemory_add_hash_id()

void timemory_add_hash_id ( uint64_t  id,
const char *  name 
)

Definition at line 392 of file trace.cpp.

393 {
395 if(!lk)
396 {
398 fprintf(stderr,
399 "[timemory-trace]> timemory_add_hash_id failed: locked...\n");
400 return;
401 }
403 fprintf(stderr, "[timemory-trace]> adding '%s' with hash %lu...\n", name,
404 (unsigned long) id);
405 auto _id = tim::add_hash_id(name);
406 if(_id != id)
407 tim::add_hash_id(_id, id);
408
409 // master thread adds the ids
410 if(tim::threading::get_id() == 0)
411 {
412 master_hash_ids[id] = name;
413 if(_id != id)
414 master_hash_ids[_id] = name;
415 }
416 }
hash_value_t add_hash_id(hash_map_ptr_t &_hash_map, string_view_cref_t _prefix)
add an string to the given hash-map (if it doesn't already exist) and return the hash
Definition: types.hpp:190
A lightweight synchronization object for preventing recursion. The first template parameter should ha...
Definition: trace.hpp:135

References tim::debug.

Referenced by timemory_add_hash_ids().

◆ timemory_add_hash_ids()

void timemory_add_hash_ids ( uint64_t  nentries,
uint64_t *  ids,
const char **  names 
)

Definition at line 420 of file trace.cpp.

421 {
423 fprintf(stderr, "[timemory-trace]> adding %lu hash ids...\n",
424 (unsigned long) nentries);
425 for(uint64_t i = 0; i < nentries; ++i)
426 timemory_add_hash_id(ids[i], names[i]);
427 }
void timemory_add_hash_id(uint64_t id, const char *name)
Definition: trace.cpp:392

References tim::debug, and timemory_add_hash_id().

◆ timemory_copy_hash_ids()

void timemory_copy_hash_ids ( )

Definition at line 431 of file trace.cpp.

432 {
434 static thread_local bool once_per_thread = false;
435 if(!once_per_thread && tim::threading::get_id() > 0)
436 {
438 fprintf(stderr, "[timemory-trace]> copying hash ids...\n");
439 once_per_thread = true;
440 auto _master_ids = master_hash_ids;
441 for(const auto& itr : _master_ids)
442 timemory_add_hash_id(itr.first, itr.second.c_str());
443 }
444 }

References tim::debug.

Referenced by timemory_push_trace_hash().

◆ timemory_is_throttled()

bool timemory_is_throttled ( const char *  name)

Definition at line 374 of file trace.cpp.

375 {
376 size_t _id = tim::get_hash_id(name);
377 return (get_throttle()->count(_id) > 0);
378 }
hash_value_t get_hash_id(Tp &&_prefix)
Definition: types.hpp:143

◆ timemory_pop_trace()

void timemory_pop_trace ( const char *  name)

Definition at line 632 of file trace.cpp.

633 {
634 uint64_t _hash = std::numeric_limits<uint64_t>::max();
635 {
637 if(!get_library_state()[0] || get_library_state()[1])
638 return;
639 _hash = tim::get_hash_id(name);
640 }
642 }
::tim::statistics< Tp > max(::tim::statistics< Tp > lhs, const Tp &rhs)
Definition: statistics.hpp:320
void timemory_pop_trace_hash(uint64_t id)
Definition: trace.cpp:514
std::array< bool, 2 > & get_library_state()
Definition: library.cpp:127

References get_library_state(), std::max(), and timemory_pop_trace_hash().

◆ timemory_pop_trace_hash()

void timemory_pop_trace_hash ( uint64_t  id)

Definition at line 514 of file trace.cpp.

515 {
517 if(!get_library_state()[0] || get_library_state()[1])
518 return;
519
520 auto& _trace_map = get_trace_map();
521 if(!tim::settings::enabled() && _trace_map.empty())
522 {
523 if(tim::settings::debug() && _trace_map.empty())
524 fprintf(stderr,
525 "[timemory-trace]> timemory_pop_trace_hash(%lu) failed. "
526 "trace_map empty...\n",
527 (unsigned long) id);
528 return;
529 }
530
531 int64_t ntotal = _trace_map[id].size();
532 int64_t offset = ntotal - 1;
533
535 {
536 auto itr = tim::get_hash_ids()->find(id);
537 string_t name = (itr != tim::get_hash_ids()->end()) ? itr->second : "unknown";
538 fprintf(stderr,
539 "ending trace for '%s' (id = %llu, offset = %lli, rank = %i, pid = "
540 "%i, thread = %i)...\n",
541 name.c_str(), (long long unsigned) id, (long long int) offset,
542 tim::dmp::rank(), (int) tim::process::get_id(),
543 (int) tim::threading::get_id());
544 }
545
546 (*get_overhead())[id].first.stop();
547
548 // if there were no entries, return (pop called without a push)
549 if(offset < 0)
550 return;
551
552 if(offset >= 0 && ntotal > 0)
553 {
554 _trace_map[id].back().stop();
555 _trace_map[id].pop_back();
556 }
557
558 if(get_throttle() && get_throttle()->count(id) > 0)
559 return;
560
561 auto _count = ++(get_overhead()->at(id).second);
562
563 if(_count % tim::settings::throttle_count() == 0)
564 {
565 auto _accum = get_overhead()->at(id).first.get_accum() / _count;
566 if(_accum < tim::settings::throttle_value())
567 {
569 {
570 auto name = tim::get_hash_ids()->find(id)->second;
571 fprintf(
572 stderr,
573 "[timemory-trace]> Throttling all future calls to '%s' on rank = "
574 "%i, pid = "
575 "%i, thread = %i. avg runtime = %lu ns from %lu invocations... "
576 "Consider eliminating from instrumentation...\n",
577 name.c_str(), tim::dmp::rank(), (int) tim::process::get_id(),
578 (int) tim::threading::get_id(), (unsigned long) _accum,
579 (unsigned long) _count);
580 }
581 get_throttle()->insert(id);
582 }
583 else
584 {
585 if(_accum < (10 * tim::settings::throttle_value()) &&
587 {
588 auto name = tim::get_hash_ids()->find(id)->second;
589 fprintf(
590 stderr,
591 "[timemory-trace]> Warning! function call '%s' within an order "
592 "of magnitude of threshold for throttling value on rank = %i, "
593 "pid = "
594 "%i, thread = %i. avg runtime = %lu ns from %lu invocations... "
595 "Consider eliminating from instrumentation...\n",
596 name.c_str(), tim::dmp::rank(), (int) tim::process::get_id(),
597 (int) tim::threading::get_id(), (unsigned long) _accum,
598 (unsigned long) _count);
599 }
600 }
601 get_overhead()->at(id).first.reset();
602 get_overhead()->at(id).second = 0;
603 }
604 }
std::string string_t
Definition: library.cpp:57
hash_map_ptr_t & get_hash_ids()
throttle_value
Definition: settings.cpp:1680
throttle_count
Definition: settings.cpp:1678

References get_library_state().

Referenced by timemory_pop_trace().

◆ timemory_push_trace()

void timemory_push_trace ( const char *  name)

Definition at line 608 of file trace.cpp.

609 {
611 timemory_trace_init("", true, "");
612
613 uint64_t _hash = std::numeric_limits<uint64_t>::max();
614 {
617 PRINT_HERE("rank = %i, pid = %i, thread = %i, name = %s",
618 tim::dmp::rank(), (int) tim::process::get_id(),
619 (int) tim::threading::get_id(), name);
620
621 if(!get_library_state()[0] || get_library_state()[1] ||
623 return;
624
625 _hash = tim::add_hash_id(name);
626 }
628 }
void timemory_trace_init(const char *comps, bool read_command_line, const char *cmd)
Definition: trace.cpp:671
void timemory_push_trace_hash(uint64_t id)
Definition: trace.cpp:448
bool timemory_trace_is_initialized()
Definition: trace.cpp:366
#define PRINT_HERE(...)
Definition: macros.hpp:152

References tim::debug, tim::enabled, get_library_state(), std::max(), PRINT_HERE, timemory_push_trace_hash(), timemory_trace_init(), and timemory_trace_is_initialized().

◆ timemory_push_trace_hash()

void timemory_push_trace_hash ( uint64_t  id)

Definition at line 448 of file trace.cpp.

449 {
451 timemory_trace_init("", true, "");
452
453 static thread_local auto _copied = (timemory_copy_hash_ids(), true);
455
457
458 if(!lk)
459 {
460#if defined(DEBUG) || !defined(NDEBUG)
462 PRINT_HERE("Tracing is locked: %s", (lk) ? "Y" : "N");
463#endif
464 return;
465 }
466
468 {
469#if defined(DEBUG) || !defined(NDEBUG)
471 PRINT_HERE("Invalid library state: init = %s, fini = %s, enabled = %s",
472 (get_library_state()[0]) ? "Y" : "N",
473 (get_library_state()[1]) ? "Y" : "N",
474 (tim::settings::enabled()) ? "Y" : "N");
475#endif
476 return;
477 }
478
479 if(get_throttle()->count(id) > 0)
480 {
481#if defined(DEBUG) || !defined(NDEBUG)
483 PRINT_HERE("trace %llu is throttled", (unsigned long long) id);
484#endif
485 return;
486 }
487
488 auto& _trace_map = get_trace_map();
489 auto& _overh_map = *get_overhead();
490
491 if(tim::get_hash_ids()->find(id) == tim::get_hash_ids()->end())
492 return;
493
495 {
496 int64_t n = _trace_map[id].size();
497 auto itr = tim::get_hash_ids()->find(id);
498 string_t name = (itr != tim::get_hash_ids()->end()) ? itr->second : "unknown";
499 fprintf(stderr,
500 "beginning trace for '%s' (id = %llu, offset = %lli, rank = %i, pid "
501 "= %i, thread = %i)...\n",
502 name.c_str(), (long long unsigned) id, (long long int) n,
503 tim::dmp::rank(), (int) tim::process::get_id(),
504 (int) tim::threading::get_id());
505 }
506
507 _trace_map[id].emplace_back(traceset_t{ id });
508 _trace_map[id].back().start();
509 _overh_map[id].first.start();
510 }
return _hash_map end()
void consume_parameters(ArgsT &&...)
Definition: types.hpp:285
This is a variadic component wrapper which combines the features of tim::component_tuple<T....
Definition: types.hpp:63
void timemory_copy_hash_ids()
Definition: trace.cpp:431

References tim::consume_parameters(), tim::debug, tim::enabled, get_library_state(), PRINT_HERE, timemory_copy_hash_ids(), timemory_trace_init(), and timemory_trace_is_initialized().

Referenced by timemory_push_trace().

◆ timemory_reset_throttle()

void timemory_reset_throttle ( const char *  name)

Definition at line 382 of file trace.cpp.

383 {
384 size_t _id = tim::get_hash_id(name);
385 auto itr = get_throttle()->find(_id);
386 if(itr != get_throttle()->end())
387 get_throttle()->erase(itr);
388 }

◆ timemory_trace_finalize()

void timemory_trace_finalize ( void  )

Definition at line 808 of file trace.cpp.

809 {
811 if(library_trace_count.load() == 0)
812 return;
813
814 auto _manager = tim::manager::master_instance();
816 if(!_manager || !_settings)
817 return;
818
819 auto _debug = _settings->get_debug();
820 if(_settings->get_verbose() > 1 || _settings->get_debug())
821 PRINT_HERE("rank = %i, pid = %i, thread = %i", tim::dmp::rank(),
822 (int) tim::process::get_id(), (int) tim::threading::get_id());
823
824 CONDITIONAL_PRINT_HERE(_debug, "%s", "getting count");
825 // do the finalization
826 auto _count = --library_trace_count;
827
828 if(_count > 0)
829 {
830 CONDITIONAL_PRINT_HERE(_debug, "%s", "positive count");
831 // have the manager finalize
833 tim::manager::instance()->finalize();
834 CONDITIONAL_PRINT_HERE(_debug, "%s", "returning");
835 return;
836 }
837
838 CONDITIONAL_PRINT_HERE(_debug, "%s", "secondary lock");
839 tim::auto_lock_t lock(tim::type_mutex<TIMEMORY_API>());
840
841 CONDITIONAL_PRINT_HERE(_debug, "%s", "setting state");
842 // tim::settings::enabled() = false;
843 get_library_state()[1] = true;
844
845 CONDITIONAL_PRINT_HERE(_debug, "%s", "barrier");
846 tim::mpi::barrier();
847
848 CONDITIONAL_PRINT_HERE(_debug, "%s", "resetting");
849 // reset traces just in case
851
852 // if already finalized
853 bool _skip_stop = false;
854 if(!_manager || _manager->is_finalized())
855 _skip_stop = true;
856
857 // clean up any remaining entries
858 if(!_skip_stop)
859 {
860 CONDITIONAL_PRINT_HERE(_debug, "%s", "cleaning trace map");
861 for(auto& itr : get_trace_map())
862 {
863 for(auto& eitr : itr.second)
864 eitr.stop();
865 // delete all the records
866 itr.second.clear();
867 }
868 CONDITIONAL_PRINT_HERE(_debug, "%s", "clearing trace map");
869 // delete all the records
870 get_trace_map().clear();
871 }
872
873 CONDITIONAL_PRINT_HERE(_debug, "%s", "resetting mpi gotcha");
874 // deactivate the gotcha wrappers
875 if(use_mpi_gotcha)
876 mpi_gotcha_handle.reset();
877
878 CONDITIONAL_PRINT_HERE(_debug, "%s", "finalizing library");
879 // finalize the library
881
882 CONDITIONAL_PRINT_HERE(_debug, "%s", "finalized trace");
883 }
static pointer_t instance()
Get a shared pointer to the instance for the current thread.
static pointer_t master_instance()
Get a shared pointer to the instance on the primary thread.
void timemory_finalize_library(void)
Finalizes timemory. Output will be generated. Any attempt to store data within timemory storage is un...
Definition: library.cpp:253
void reset(TupleT< Tp... > &obj, Args &&... args)
Definition: functional.cpp:599
std::unique_lock< mutex_t > auto_lock_t
Unique lock type around mutex_t.
Definition: locking.hpp:42
char argparse::argument_parser tim::settings * _settings
Definition: config.cpp:255
static settings * instance()
Definition: settings.hpp:536
#define CONDITIONAL_PRINT_HERE(CONDITION,...)
Definition: macros.hpp:183

◆ timemory_trace_init()

void timemory_trace_init ( const char *  comps,
bool  read_command_line,
const char *  cmd 
)

Definition at line 671 of file trace.cpp.

672 {
674 if(!tim::manager::instance() || tim::manager::instance()->is_finalized())
675 return;
676
677 // configures the output path
678 auto _configure_output_path = [&]() {
679 static bool _performed_explicit = false;
680 if(_performed_explicit || tim::settings::output_path() != "timemory-output")
681 return;
683 {
684 auto _init = [](int _ac, char** _av) { timemory_init_library(_ac, _av); };
686 }
687 else
688 {
689 std::string exe_name = (cmd) ? cmd : "";
690 if(!exe_name.empty())
691 _performed_explicit = true;
692
693 while(exe_name.find('\\') != std::string::npos)
694 exe_name = exe_name.substr(exe_name.find_last_of('\\') + 1);
695 while(exe_name.find('/') != std::string::npos)
696 exe_name = exe_name.substr(exe_name.find_last_of('/') + 1);
697
698 static const std::vector<std::string> _exe_suffixes = { ".py", ".exe" };
699 for(const auto& ext : _exe_suffixes)
700 {
701 if(exe_name.find(ext) != std::string::npos)
702 exe_name.erase(exe_name.find(ext), ext.length() + 1);
703 }
704
705 exe_name = std::string("timemory-") + exe_name + "-output";
706 for(auto& itr : exe_name)
707 {
708 if(itr == '_')
709 itr = '-';
710 }
711
713 }
715 tim::manager::instance()->update_metadata_prefix();
716 };
717
718 // write the info about the rank/pid/thread/command
719 auto _write_info = [&]() {
720 std::stringstream _info;
721 _info << "[timemory_trace_init]> ";
722 if(tim::dmp::is_initialized())
723 _info << "rank = " << tim::dmp::rank() << ", ";
724 _info << "pid = " << tim::process::get_id() << ", ";
725 _info << "tid = " << tim::threading::get_id();
726 if(cmd && strlen(cmd) > 0)
727 _info << ", command: " << cmd;
728 if(comps && strlen(comps) > 0)
729 _info << ", default components: " << comps;
730 fprintf(stderr, "%s\n", _info.str().c_str());
731 };
732
733 // configures the tracing components
734 auto _configure_components = [&]() {
735 if(comps && strlen(comps) > 0)
736 {
737 _write_info();
738 tim::set_env<std::string>("TIMEMORY_TRACE_COMPONENTS", comps, 0);
741 }
742
744
745 // configure bundle
746 user_trace_bundle::global_init(true);
747 // tim::operation::init<user_trace_bundle>(
748 // tim::operation::mode_constant<tim::operation::init_mode::global>{});
749 };
750
751 if(!get_library_state()[0] && library_trace_count++ == 0)
752 {
753 _configure_components();
754 _configure_output_path();
755
757 get_library_state()[0] = true;
758
759 auto _exit_action = [](int nsig) {
760 auto _manager = tim::manager::master_instance();
761 if(_manager && !_manager->is_finalized() && !_manager->is_finalizing())
762 {
763 std::cout << "Finalizing after signal: " << nsig << " :: "
765 static_cast<tim::sys_signal>(nsig))
766 << std::endl;
768 }
769 };
771 std::atexit(&timemory_trace_finalize);
772#if !defined(TIMEMORY_MACOS)
773 // Apple clang version 11.0.3 (clang-1103.0.32.62) doesn't seem to have this
774 // function
775 std::at_quick_exit(&tim::timemory_finalize);
776#endif
777
778#if defined(TIMEMORY_MPI_GOTCHA)
779 if(!mpi_gotcha_handle.get())
780 {
781 mpi_gotcha_handle =
782 std::make_shared<mpi_trace_bundle_t>("timemory_trace_mpi_gotcha");
783 mpi_trace_gotcha::get_trace_components() = comps;
785 mpi_trace_gotcha::get_command() = (cmd) ? cmd : "";
786 if(mpi_is_attached)
787 mpi_trace_gotcha::set_attr();
788 mpi_gotcha_handle->start();
789 }
790 else if(mpi_gotcha_handle.get())
791 {
792 tim::manager::instance()->update_metadata_prefix();
793 }
794#endif
795 }
796 else
797 {
799 PRINT_HERE("trace already initialized: %s",
800 (get_library_state()[0]) ? "Y" : "N");
801
802 _configure_components();
803 }
804 }
static void use_exit_hook(bool val)
Enable setting std::exit callback.
Definition: manager.hpp:176
static std::string str(const sys_signal &)
Definition: signals.hpp:147
static void set_exit_action(signal_function_t _f)
Definition: signals.hpp:280
void timemory_init_library(int argc, char **argv)
Initializes timemory. Not strictly necessary but highly recommended.
Definition: library.cpp:212
void read_command_line(Func &&_func)
this only works on Linux where there is a /proc/<PID>/cmdline file
Definition: config.hpp:65
void timemory_finalize()
finalization of the specified types
std::string exe_name
Definition: config.cpp:77
sys_signal
Definition: declaration.hpp:69
tim::mpl::apply< std::string > string
Definition: macros.hpp:53
output_path
Definition: settings.cpp:1661
trace_components
Definition: settings.cpp:1694
static void parse(settings *=instance< TIMEMORY_API >())
Definition: settings.cpp:410
void timemory_trace_finalize(void)
Definition: trace.cpp:808

References tim::plotting::cmd, tim::exe_name, tim::manager::instance(), tim::output_path, tim::config::read_command_line(), and timemory_init_library().

Referenced by timemory_push_trace(), and timemory_push_trace_hash().

◆ timemory_trace_is_initialized()

bool timemory_trace_is_initialized ( void  )

Definition at line 366 of file trace.cpp.

367 {
368 return (get_library_state()[0] &&
369 library_trace_count.load(std::memory_order_relaxed) > 0);
370 }

References get_library_state().

Referenced by timemory_push_trace(), and timemory_push_trace_hash().

◆ timemory_trace_set_env()

void timemory_trace_set_env ( const char *  env_var,
const char *  env_val 
)

Definition at line 658 of file trace.cpp.

659 {
661 tim::set_env<std::string>(env_var, env_val, 0);
662 if(get_library_state()[0])
663 {
665 user_trace_bundle::global_init(true);
666 }
667 }

References get_library_state(), and tim::settings::parse().