47 ) : name {n}, type {t}, beg {b}, end {e} {
67 Timeline(
const Timeline& rhs) =
delete;
68 Timeline(Timeline&& rhs) =
default;
70 Timeline& operator = (
const Timeline& rhs) =
delete;
71 Timeline& operator = (Timeline&& rhs) =
default;
91 ProfileData() =
default;
93 ProfileData(
const ProfileData& rhs) =
delete;
94 ProfileData(ProfileData&& rhs) =
default;
96 ProfileData& operator = (
const ProfileData& rhs) =
delete;
97 ProfileData& operator = (ProfileData&&) =
default;
184 virtual void set_up(
size_t num_workers) = 0;
282 inline void set_up(
size_t num_workers)
override final;
290inline ChromeObserver::Segment::Segment(
293 name {n}, beg {b}, end {e} {
297inline void ChromeObserver::set_up(
size_t num_workers) {
298 _timeline.segments.resize(num_workers);
299 _timeline.stacks.resize(num_workers);
301 for(
size_t w=0; w<num_workers; ++w) {
302 _timeline.segments[w].reserve(32);
305 _timeline.origin = observer_stamp_t::clock::now();
309inline void ChromeObserver::on_entry(WorkerView wv, TaskView) {
310 _timeline.stacks[wv.id()].push(observer_stamp_t::clock::now());
314inline void ChromeObserver::on_exit(WorkerView wv, TaskView tv) {
318 assert(!_timeline.stacks[w].empty());
320 auto beg = _timeline.stacks[w].top();
321 _timeline.stacks[w].pop();
323 _timeline.segments[w].emplace_back(
324 tv.name(), beg, observer_stamp_t::clock::now()
330 for(
size_t w=0; w<_timeline.segments.size(); ++w) {
331 _timeline.segments[w].clear();
332 while(!_timeline.stacks[w].empty()) {
333 _timeline.stacks[w].pop();
343 for(first = 0; first<_timeline.segments.size(); ++first) {
344 if(_timeline.segments[first].size() > 0) {
351 for(
size_t w=first; w<_timeline.segments.size(); w++) {
353 if(w != first && _timeline.segments[w].size() > 0) {
357 for(
size_t i=0; i<_timeline.segments[w].size(); i++) {
360 <<
"\"cat\":\"ChromeObserver\",";
364 if(_timeline.segments[w][i].name.empty()) {
368 os << _timeline.segments[w][i].name;
373 os <<
"\"ph\":\"X\","
375 <<
"\"tid\":" << w <<
','
376 <<
"\"ts\":" << std::chrono::duration_cast<std::chrono::microseconds>(
377 _timeline.segments[w][i].beg - _timeline.origin
379 <<
"\"dur\":" << std::chrono::duration_cast<std::chrono::microseconds>(
380 _timeline.segments[w][i].end - _timeline.segments[w][i].beg
383 if(i != _timeline.segments[w].size() - 1) {
404 _timeline.segments.begin(), _timeline.segments.end(),
size_t{0},
405 [](
size_t sum,
const auto& exe){
406 return sum + exe.size();
450 friend class TFProfManager;
481 inline void set_up(
size_t num_workers)
override final;
487inline void TFProfObserver::set_up(
size_t num_workers) {
488 _timeline.uid = unique_id<size_t>();
489 _timeline.origin = observer_stamp_t::clock::now();
490 _timeline.segments.resize(num_workers);
491 _stacks.resize(num_workers);
495inline void TFProfObserver::on_entry(WorkerView wv, TaskView) {
496 _stacks[wv.id()].push(observer_stamp_t::clock::now());
500inline void TFProfObserver::on_exit(WorkerView wv, TaskView tv) {
504 assert(!_stacks[w].empty());
506 if(_stacks[w].size() > _timeline.segments[w].size()) {
507 _timeline.segments[w].resize(_stacks[w].size());
510 auto beg = _stacks[w].top();
513 _timeline.segments[w][_stacks[w].size()].emplace_back(
514 tv.name(), tv.type(), beg, observer_stamp_t::clock::now()
520 for(
size_t w=0; w<_timeline.segments.size(); ++w) {
521 for(
size_t l=0; l<_timeline.segments[w].size(); ++l) {
522 _timeline.segments[w][l].clear();
524 while(!_stacks[w].empty()) {
535 for(first = 0; first<_timeline.segments.size(); ++first) {
536 if(_timeline.segments[first].size() > 0) {
542 if(first == _timeline.segments.size()) {
547 os <<
"{\"executor\":\"" << _timeline.uid <<
"\",\"data\":[";
551 for(
size_t w=first; w<_timeline.segments.size(); w++) {
552 for(
size_t l=0; l<_timeline.segments[w].size(); l++) {
554 if(_timeline.segments[w][l].empty()) {
565 os <<
"{\"worker\":" << w <<
",\"level\":" << l <<
",\"data\":[";
566 for(
size_t i=0; i<_timeline.segments[w][l].size(); ++i) {
568 const auto& s = _timeline.segments[w][l][i];
574 << std::chrono::duration_cast<std::chrono::microseconds>(
575 s.beg - _timeline.origin
577 << std::chrono::duration_cast<std::chrono::microseconds>(
578 s.end - _timeline.origin
592 os <<
"\"type\":\"" <<
to_string(s.type) <<
"\"";
613 _timeline.segments.begin(), _timeline.segments.end(),
size_t{0},
614 [](
size_t sum,
const auto& exe){
615 return sum + exe.size();
635 TFProfManager(
const TFProfManager&) =
delete;
636 TFProfManager& operator=(
const TFProfManager&) =
delete;
638 static TFProfManager& get();
655inline TFProfManager::TFProfManager() :
656 _fpath {get_env(TF_ENABLE_PROFILER)} {
663 _observers.push_back(
std::move(observer));
667inline void TFProfManager::dump(
std::ostream& os)
const {
668 for(
size_t i=0; i<_observers.size(); ++i) {
670 _observers[i]->dump(os);
675inline TFProfManager::~TFProfManager() {
699 for(
size_t i=0; i<_observers.size(); ++i) {
701 _observers[i]->dump(ofs);
708inline TFProfManager& TFProfManager::get() {
709 static TFProfManager mgr;
733 case ObserverType::TFPROF:
return "tfprof";
734 case ObserverType::CHROME:
return "chrome";
735 default:
return "undefined";
class to create an observer based on Chrome tracing format
Definition observer.hpp:231
void clear()
clears the timeline data
Definition observer.hpp:329
std::string dump() const
dumps the timelines into a Chrome Tracing format
Definition observer.hpp:395
size_t num_tasks() const
queries the number of tasks observed
Definition observer.hpp:402
class to create an executor for running a taskflow graph
Definition executor.hpp:50
class to derive an executor observer
Definition observer.hpp:169
virtual void on_entry(WorkerView w, TaskView task_view)=0
method to call before a worker thread executes a closure
virtual void set_up(size_t num_workers)=0
constructor-like method to call when the executor observer is fully created
virtual void on_exit(WorkerView w, TaskView task_view)=0
method to call after a worker thread executed a closure
virtual ~ObserverInterface()=default
virtual destructor
class to create an observer based on the built-in taskflow profiler format
Definition observer.hpp:447
std::string dump() const
dumps the timelines into a JSON string
Definition observer.hpp:604
void clear()
clears the timeline data
Definition observer.hpp:519
size_t num_tasks() const
queries the number of tasks observed
Definition observer.hpp:611
class to access task information from the observer interface
Definition task.hpp:638
class to create an immutable view of a worker in an executor
Definition worker.hpp:78
taskflow namespace
Definition small_vector.hpp:27
TaskType
enumeration of all task types
Definition task.hpp:21
@ UNDEFINED
undefined task type (for internal use only)
const char * to_string(TaskType type)
convert a task type to a human-readable string
Definition task.hpp:81
ObserverType
enumeration of all observer types
Definition observer.hpp:722
std::chrono::time_point< std::chrono::steady_clock > observer_stamp_t
default time point type of observers
Definition observer.hpp:20