source: trunk/src/core/profiler.cc @ 371

Last change on this file since 371 was 371, checked in by epyon, 10 years ago
  • profiler - removed sstream dependency - formating via snprintf
  • profiler - string_refs where applicable (still need string for unordered_map)
  • logger - removed sstream support
  • logger - log_sequence instead of detail logger functions
File size: 3.1 KB
Line 
1// Copyright (C) 2012-2014 ChaosForge Ltd
2// This file is part of NV Libraries.
3// For conditions of distribution and use, see copyright notice in nv.hh
4
5#include "nv/core/profiler.hh"
6
7#include "nv/core/time.hh"
8#include "nv/core/logging.hh"
9#include <cstdio>
10#include <cstdlib>
11
12using namespace nv;
13
14#ifdef NV_MSVC
15#define snprintf sprintf_s
16#endif
17
18profiler::profiler()
19{
20        m_root = new node( "root", nullptr );
21        m_root->start();
22        m_current = m_root;
23}
24
25profiler::~profiler()
26{
27        delete m_root;
28}
29
30void profiler::start_profile( const string_ref& tag )
31{
32        if ( tag != m_current->m_tag )
33        {
34                m_current = m_current->request_child( tag );
35        }
36        m_current->start();
37}
38
39void profiler::stop_profile()
40{
41        if ( m_current->stop() )
42        {
43                m_current = m_current->get_parent();
44        }
45}
46
47profiler::node::node( const string_ref& tag, node* parent )
48        : m_tag( tag.to_string() )
49        , m_parent( parent )
50        , m_recusion( 0 )
51        , m_calls( 0 )
52        , m_start_time_us( 0 )
53        , m_total_time_us( 0 )
54{
55
56}
57
58profiler::node* profiler::node::request_child( const string_ref& tag )
59{
60        std::string stag( tag.to_string() );
61        auto it = m_children.find( stag );
62        if ( it != m_children.end() )
63                return it->second;
64        else
65        {
66                node* result = new node( tag, this );
67                m_children[ stag ] = result;
68                return result;
69        }
70}
71
72void profiler::node::start()
73{
74        m_calls++;
75        m_recusion++;
76        if ( m_recusion == 1 )
77        {
78                m_start_time_us = get_system_us();
79        }
80}
81
82bool profiler::node::stop()
83{
84        m_recusion--;
85        if ( m_recusion == 0 )
86        {
87                uint64 stop_time_us = get_system_us();
88                uint64 elapsed_us   = stop_time_us - m_start_time_us;
89                m_total_time_us     += elapsed_us;
90                return true;
91        }
92        return false;
93}
94
95
96nv::profiler::node::~node()
97{
98        for ( const auto& pair : m_children )
99        {
100                delete pair.second;
101        }
102}
103
104void profiler::log_report()
105{
106        m_root->stop();
107        NV_LOG_INFO( "-- PROFILER REPORT -------------------------------------" );
108        char buffer[128];
109        snprintf( buffer, 128, "%-23s %6s %6s %9s %6s", "TAG", "%PARNT", "CALLS", "TOTAL(ms)", "AVG(ms)" );
110        NV_LOG_INFO( string_ref( buffer, strlen(buffer) ) );
111        log_node_children( 0, m_root );
112        NV_LOG_INFO( "-- PROFILER REPORT END ---------------------------------" );
113        m_root->start();
114}
115
116void profiler::log_node_children( uint32 indent, const node* n )
117{
118        char buffer[128];
119        for ( const auto& pair : n->m_children )
120        {
121                const node* c = pair.second;
122                if ( c->m_calls > 0 )
123                {
124                        double pparent  = ( (double)c->m_total_time_us / (double)c->m_parent->m_total_time_us ) * 100.f;
125                        int calls       = c->m_calls;
126                        double total_ms = c->m_total_time_us / 1000.f;
127                        double avg_ms   = ( (double)c->m_total_time_us / (double)c->m_calls ) / 1000.f;
128                        if ( indent > 0 ) memset( buffer, '-', indent );
129                        snprintf( buffer + indent, 128 - indent, "%*.*s %6.2f %6d %9.2f %6.2f", indent - 23, 23 - indent,
130                                c->m_tag.c_str(), pparent, calls, total_ms, avg_ms );
131                        NV_LOG_INFO( string_ref( buffer, strlen( buffer ) ) );
132                        if ( c->m_children.size() > 0 )
133                        {
134                                log_node_children( indent + 1, c );
135                        }
136                }
137        }
138}
Note: See TracBrowser for help on using the repository browser.