[319] | 1 | // Copyright (C) 2012-2014 ChaosForge Ltd
|
---|
[150] | 2 | // This file is part of NV Libraries.
|
---|
| 3 | // For conditions of distribution and use, see copyright notice in nv.hh
|
---|
| 4 |
|
---|
[319] | 5 | #include "nv/core/profiler.hh"
|
---|
[150] | 6 |
|
---|
| 7 | #include <iomanip>
|
---|
| 8 | #include <ios>
|
---|
[319] | 9 | #include "nv/core/time.hh"
|
---|
[150] | 10 |
|
---|
| 11 | using namespace nv;
|
---|
| 12 |
|
---|
| 13 |
|
---|
| 14 | profiler::profiler()
|
---|
| 15 | {
|
---|
| 16 | m_root = new node( "root", nullptr );
|
---|
| 17 | m_root->start();
|
---|
| 18 | m_current = m_root;
|
---|
| 19 | }
|
---|
| 20 |
|
---|
| 21 | profiler::~profiler()
|
---|
| 22 | {
|
---|
| 23 | delete m_root;
|
---|
| 24 | }
|
---|
| 25 |
|
---|
| 26 | void profiler::start_profile( const char* tag )
|
---|
| 27 | {
|
---|
| 28 | if ( tag != m_current->m_tag )
|
---|
| 29 | {
|
---|
| 30 | m_current = m_current->request_child( tag );
|
---|
| 31 | }
|
---|
| 32 | m_current->start();
|
---|
| 33 | }
|
---|
| 34 |
|
---|
| 35 | void profiler::stop_profile()
|
---|
| 36 | {
|
---|
| 37 | if ( m_current->stop() )
|
---|
| 38 | {
|
---|
| 39 | m_current = m_current->get_parent();
|
---|
| 40 | }
|
---|
| 41 | }
|
---|
| 42 |
|
---|
| 43 | profiler::node::node( const char* tag, node* parent )
|
---|
| 44 | : m_tag( tag )
|
---|
| 45 | , m_parent( parent )
|
---|
| 46 | , m_recusion( 0 )
|
---|
| 47 | , m_calls( 0 )
|
---|
| 48 | , m_start_time_us( 0 )
|
---|
| 49 | , m_total_time_us( 0 )
|
---|
| 50 | {
|
---|
| 51 |
|
---|
| 52 | }
|
---|
| 53 |
|
---|
| 54 | profiler::node* profiler::node::request_child( const char* tag )
|
---|
| 55 | {
|
---|
| 56 | auto it = m_children.find( tag );
|
---|
| 57 | if ( it != m_children.end() )
|
---|
| 58 | return it->second;
|
---|
| 59 | else
|
---|
| 60 | {
|
---|
| 61 | node* result = new node( tag, this );
|
---|
| 62 | m_children[ tag ] = result;
|
---|
| 63 | return result;
|
---|
| 64 | }
|
---|
| 65 | }
|
---|
| 66 |
|
---|
| 67 | void profiler::node::start()
|
---|
| 68 | {
|
---|
| 69 | m_calls++;
|
---|
| 70 | m_recusion++;
|
---|
| 71 | if ( m_recusion == 1 )
|
---|
| 72 | {
|
---|
| 73 | m_start_time_us = get_system_us();
|
---|
| 74 | }
|
---|
| 75 | }
|
---|
| 76 |
|
---|
| 77 | bool profiler::node::stop()
|
---|
| 78 | {
|
---|
| 79 | m_recusion--;
|
---|
| 80 | if ( m_recusion == 0 )
|
---|
| 81 | {
|
---|
| 82 | uint64 stop_time_us = get_system_us();
|
---|
| 83 | uint64 elapsed_us = stop_time_us - m_start_time_us;
|
---|
| 84 | m_total_time_us += elapsed_us;
|
---|
| 85 | return true;
|
---|
| 86 | }
|
---|
| 87 | return false;
|
---|
| 88 | }
|
---|
| 89 |
|
---|
| 90 |
|
---|
| 91 | nv::profiler::node::~node()
|
---|
| 92 | {
|
---|
| 93 | for ( const auto& pair : m_children )
|
---|
| 94 | {
|
---|
| 95 | delete pair.second;
|
---|
| 96 | }
|
---|
| 97 | }
|
---|
| 98 |
|
---|
| 99 |
|
---|
| 100 | void profiler::log_report()
|
---|
| 101 | {
|
---|
| 102 | m_root->stop();
|
---|
| 103 | NV_LOG( LOG_INFO, "-- PROFILER REPORT -----------------------------------------" );
|
---|
[151] | 104 | NV_LOG( LOG_INFO, std::left << std::setw(24) << "TAG"
|
---|
[150] | 105 | << std::setw(7) << "%PARNT"
|
---|
| 106 | << std::setw(7) << "CALLS"
|
---|
| 107 | << std::setw(10) << "TOTAL(ms)"
|
---|
| 108 | << std::setw(10) << "AVG(ms)" );
|
---|
| 109 | log_node_children( "", m_root );
|
---|
| 110 | NV_LOG( LOG_INFO, "-- PROFILER REPORT END -------------------------------------" );
|
---|
| 111 | m_root->start();
|
---|
| 112 | }
|
---|
| 113 |
|
---|
| 114 | void profiler::log_node_children( const std::string& ind, const node* n )
|
---|
| 115 | {
|
---|
| 116 | for ( const auto& pair : n->m_children )
|
---|
| 117 | {
|
---|
| 118 | const node* c = pair.second;
|
---|
| 119 | if ( c->m_calls > 0 )
|
---|
| 120 | {
|
---|
| 121 | NV_LOG( LOG_INFO, std::left << std::setw(24) << ind + c->m_tag
|
---|
| 122 | << std::setw(7) << std::setprecision(2) << std::fixed << ( (double)c->m_total_time_us / (double)c->m_parent->m_total_time_us ) * 100.0
|
---|
| 123 | << std::setw(7) << c->m_calls
|
---|
| 124 | << std::setw(10) << std::setprecision(2) << std::fixed << c->m_total_time_us / 1000.f
|
---|
| 125 | << std::setw(10) << std::setprecision(2) << std::fixed << ( (double)c->m_total_time_us / (double)c->m_calls ) / 1000.f
|
---|
| 126 | );
|
---|
| 127 | if ( c->m_children.size() > 0 )
|
---|
| 128 | {
|
---|
| 129 | log_node_children( ind + "-", c );
|
---|
| 130 | }
|
---|
| 131 | }
|
---|
| 132 | }
|
---|
| 133 | }
|
---|