diff options
Diffstat (limited to '')
-rw-r--r-- | src/unstable/profiler.cpp | 184 | ||||
-rw-r--r-- | src/unstable/profiler.h | 54 |
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 | |||
7 | Bu::Profiler::Profiler() | ||
8 | { | ||
9 | } | ||
10 | |||
11 | Bu::Profiler::~Profiler() | ||
12 | { | ||
13 | printReport(); | ||
14 | } | ||
15 | |||
16 | uint64_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 | |||
23 | void 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 | |||
36 | void 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 | |||
48 | void 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 | |||
141 | Bu::Profiler::Event::Event() : | ||
142 | iStart( Bu::Profiler::getMicroTime() ), | ||
143 | iStop( 0 ) | ||
144 | { | ||
145 | } | ||
146 | |||
147 | Bu::Profiler::Event::Event( const Event &rSrc ) : | ||
148 | iStart( rSrc.iStart ), | ||
149 | iStop( rSrc.iStop ) | ||
150 | { | ||
151 | } | ||
152 | |||
153 | Bu::Profiler::Event::~Event() | ||
154 | { | ||
155 | } | ||
156 | |||
157 | void Bu::Profiler::Event::end() | ||
158 | { | ||
159 | if( iStop == 0 ) | ||
160 | iStop = Bu::Profiler::getMicroTime(); | ||
161 | } | ||
162 | |||
163 | bool Bu::Profiler::Event::hasEnded() const | ||
164 | { | ||
165 | return iStop != 0; | ||
166 | } | ||
167 | |||
168 | uint64_t Bu::Profiler::Event::getStart() const | ||
169 | { | ||
170 | return iStart; | ||
171 | } | ||
172 | |||
173 | uint64_t Bu::Profiler::Event::getEnd() const | ||
174 | { | ||
175 | return iStop; | ||
176 | } | ||
177 | |||
178 | uint64_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 | |||
10 | namespace 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 | ||