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

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