aboutsummaryrefslogtreecommitdiff
path: root/src/unstable
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/unstable/profiler.cpp184
-rw-r--r--src/unstable/profiler.h54
2 files changed, 238 insertions, 0 deletions
diff --git a/src/unstable/profiler.cpp b/src/unstable/profiler.cpp
new file mode 100644
index 0000000..1b176b9
--- /dev/null
+++ b/src/unstable/profiler.cpp
@@ -0,0 +1,184 @@
1#include "bu/profiler.h"
2#include "bu/mutexlocker.h"
3#include "bu/sio.h"
4
5#include <sys/time.h>
6
7Bu::Profiler::Profiler()
8{
9}
10
11Bu::Profiler::~Profiler()
12{
13 printReport();
14}
15
16uint64_t Bu::Profiler::getMicroTime()
17{
18 struct timeval tv;
19 gettimeofday( &tv, NULL );
20 return ((uint64_t)tv.tv_sec)*1000000 + ((uint64_t)tv.tv_usec);
21}
22
23void Bu::Profiler::startEvent( const Bu::Blob &bName )
24{
25 Bu::MutexLocker l( mLock );
26 if( hEvent.has( bName ) )
27 {
28 hEvent.get( bName ).append( Event() );
29 }
30 else
31 {
32 hEvent.insert( bName, EventList( Event() ) );
33 }
34}
35
36void Bu::Profiler::endEvent( const Bu::Blob &bName )
37{
38 Bu::MutexLocker l( mLock );
39 if( !hEvent.has( bName ) )
40 return;
41
42 if( hEvent.get( bName ).isEmpty() )
43 return;
44
45 hEvent.get( bName ).last().end();
46}
47
48void Bu::Profiler::printReport() const
49{
50 class Breakdown
51 {
52 public:
53 Breakdown( const Bu::Blob &bName ) :
54 bName( bName ), uCount( 0 ), uTotal( 0 ), uMin( 0 ), uMax( 0 ) { }
55 Breakdown( const Breakdown &rSrc ) :
56 bName( rSrc.bName ), uCount( rSrc.uCount ), uTotal( rSrc.uTotal ),
57 uMin( rSrc.uMin ), uMax( rSrc.uMax ) { }
58 ~Breakdown() { }
59
60 bool operator<( const Breakdown &rhs ) const
61 {
62 return uTotal > rhs.uTotal;
63 }
64 Breakdown &operator=( const Breakdown &rhs )
65 {
66 bName = rhs.bName;
67 uCount = rhs.uCount;
68 uTotal = rhs.uTotal;
69 uMin = rhs.uMin;
70 uMax = rhs.uMax;
71 return *this;
72 }
73
74 void add( uint64_t uSpan )
75 {
76 if( uCount == 0 )
77 {
78 uMin = uMax = uSpan;
79 }
80 else
81 {
82 if( uMin > uSpan )
83 uMin = uSpan;
84 if( uMax < uSpan )
85 uMax = uSpan;
86
87 }
88 uCount++;
89 uTotal += uSpan;
90 }
91
92 Bu::Blob bName;
93 uint64_t uCount;
94 uint64_t uTotal;
95 uint64_t uMin;
96 uint64_t uMax;
97 };
98 Bu::MutexLocker l( mLock );
99
100 int iTitleLen = 0;
101 Bu::List<Breakdown> lBreakdown;
102 for( EventListHash::const_iterator iType = hEvent.begin(); iType; iType++ )
103 {
104 Breakdown b( iType.getKey() );
105 if( iTitleLen < b.bName.getSize() )
106 iTitleLen = b.bName.getSize();
107 for( EventList::const_iterator iEv = iType.getValue().begin();
108 iEv; iEv++ )
109 {
110 b.add( (*iEv).getSpan() );
111 }
112 lBreakdown.append( b );
113 }
114
115 lBreakdown.sort();
116
117 Bu::println("%1 %2 %3 %4 %5 %6")
118 .arg("Title", Bu::Fmt(iTitleLen) )
119 .arg("Cnt", Bu::Fmt(5) )
120 .arg("Total", Bu::Fmt(9) )
121 .arg("Avg", Bu::Fmt(9) )
122 .arg("Max", Bu::Fmt(9) )
123 .arg("Min", Bu::Fmt(9) );
124 for( Bu::List<Breakdown>::iterator i = lBreakdown.begin(); i; i++ )
125 {
126 Bu::println("%1 %2 %3.%4 %5.%6 %7.%8 %9.%10")
127 .arg( (*i).bName.getData(), Bu::Fmt(iTitleLen) )
128 .arg( (*i).uCount, Bu::Fmt(5) )
129 .arg( ((*i).uTotal/1000000), Bu::Fmt(5).right() )
130 .arg( ((*i).uTotal/1000)%1000, Bu::Fmt(3).fill('0').right() )
131 .arg( ((*i).uTotal/(*i).uCount)/1000000, Bu::Fmt(5).right() )
132 .arg( (((*i).uTotal/(*i).uCount)/1000)%1000, Bu::Fmt(3).right().fill('0') )
133 .arg( (*i).uMax/1000000, Bu::Fmt(5).right() )
134 .arg( ((*i).uMax/1000)%1000, Bu::Fmt(3).right().fill('0') )
135 .arg( (*i).uMin/1000000, Bu::Fmt(5).right() )
136 .arg( ((*i).uMin/1000)%1000, Bu::Fmt(3).right().fill('0') )
137 ;
138 }
139}
140
141Bu::Profiler::Event::Event() :
142 iStart( Bu::Profiler::getMicroTime() ),
143 iStop( 0 )
144{
145}
146
147Bu::Profiler::Event::Event( const Event &rSrc ) :
148 iStart( rSrc.iStart ),
149 iStop( rSrc.iStop )
150{
151}
152
153Bu::Profiler::Event::~Event()
154{
155}
156
157void Bu::Profiler::Event::end()
158{
159 if( iStop == 0 )
160 iStop = Bu::Profiler::getMicroTime();
161}
162
163bool Bu::Profiler::Event::hasEnded() const
164{
165 return iStop != 0;
166}
167
168uint64_t Bu::Profiler::Event::getStart() const
169{
170 return iStart;
171}
172
173uint64_t Bu::Profiler::Event::getEnd() const
174{
175 return iStop;
176}
177
178uint64_t Bu::Profiler::Event::getSpan() const
179{
180 if( iStop < iStart )
181 return 0;
182 return iStop-iStart;
183}
184
diff --git a/src/unstable/profiler.h b/src/unstable/profiler.h
new file mode 100644
index 0000000..df05023
--- /dev/null
+++ b/src/unstable/profiler.h
@@ -0,0 +1,54 @@
1#ifndef BU_PROFILER_H
2#define BU_PROFILER_H
3
4#include "bu/blob.h"
5#include "bu/hash.h"
6#include "bu/list.h"
7#include "bu/mutex.h"
8#include "bu/singleton.h"
9
10namespace Bu
11{
12 class Profiler : public Bu::Singleton<Profiler>
13 {
14 friend class Bu::Singleton<Profiler>;
15 private:
16 Profiler();
17 virtual ~Profiler();
18
19 public:
20 static uint64_t getMicroTime();
21
22 void startEvent( const Bu::Blob &bName );
23 void endEvent( const Bu::Blob &bName );
24
25 void printReport() const;
26
27 private:
28 class Event
29 {
30 public:
31 Event();
32 Event( const Event &rSrc );
33 ~Event();
34
35 void end();
36 bool hasEnded() const;
37
38 uint64_t getStart() const;
39 uint64_t getEnd() const;
40 uint64_t getSpan() const;
41
42 private:
43 uint64_t iStart;
44 uint64_t iStop;
45 };
46
47 typedef Bu::List<Event> EventList;
48 typedef Bu::Hash<Bu::Blob, EventList> EventListHash;
49 EventListHash hEvent;
50 mutable Bu::Mutex mLock;
51 };
52};
53
54#endif