diff options
-rw-r--r-- | default.bld | 5 | ||||
-rw-r--r-- | src/tests/speedometer.cpp | 51 | ||||
-rw-r--r-- | src/unstable/speedometer.cpp | 120 | ||||
-rw-r--r-- | src/unstable/speedometer.h | 43 |
4 files changed, 219 insertions, 0 deletions
diff --git a/default.bld b/default.bld index dbb3772..c471744 100644 --- a/default.bld +++ b/default.bld | |||
@@ -34,6 +34,11 @@ action "all" | |||
34 | targets("tools"), targets("tests")]; | 34 | targets("tools"), targets("tests")]; |
35 | } | 35 | } |
36 | 36 | ||
37 | action "tests" | ||
38 | { | ||
39 | build: targets("tests"); | ||
40 | } | ||
41 | |||
37 | action "unit" | 42 | action "unit" |
38 | { | 43 | { |
39 | build: targets("unit tests"); | 44 | build: targets("unit tests"); |
diff --git a/src/tests/speedometer.cpp b/src/tests/speedometer.cpp new file mode 100644 index 0000000..4532f59 --- /dev/null +++ b/src/tests/speedometer.cpp | |||
@@ -0,0 +1,51 @@ | |||
1 | #include <bu/sio.h> | ||
2 | #include <bu/speedometer.h> | ||
3 | #include <bu/thread.h> | ||
4 | |||
5 | #include <unistd.h> | ||
6 | |||
7 | class Report : public Bu::Thread | ||
8 | { | ||
9 | public: | ||
10 | Report() : | ||
11 | sKeys( 500, 8 ) | ||
12 | { | ||
13 | } | ||
14 | |||
15 | ~Report() | ||
16 | { | ||
17 | } | ||
18 | |||
19 | Bu::Speedometer sKeys; | ||
20 | bool bRunning; | ||
21 | |||
22 | protected: | ||
23 | virtual void run() | ||
24 | { | ||
25 | bRunning = true; | ||
26 | while( bRunning ) | ||
27 | { | ||
28 | usleep( 500000 ); | ||
29 | // Bu::println("Speed: %1 - %2 k/s").arg( sKeys.getTotalEvents() ). | ||
30 | // arg( sKeys.getSpeed() ); | ||
31 | } | ||
32 | } | ||
33 | }; | ||
34 | |||
35 | int main( int argc, char *argv[] ) | ||
36 | { | ||
37 | Report r; | ||
38 | |||
39 | r.start(); | ||
40 | |||
41 | for(;;) | ||
42 | { | ||
43 | getchar(); | ||
44 | r.sKeys.addEvent(); | ||
45 | r.sKeys.debug(); | ||
46 | } | ||
47 | |||
48 | |||
49 | return 0; | ||
50 | } | ||
51 | |||
diff --git a/src/unstable/speedometer.cpp b/src/unstable/speedometer.cpp new file mode 100644 index 0000000..75e424e --- /dev/null +++ b/src/unstable/speedometer.cpp | |||
@@ -0,0 +1,120 @@ | |||
1 | #include "bu/speedometer.h" | ||
2 | #include "bu/mutexlocker.h" | ||
3 | #include "bu/sio.h" | ||
4 | |||
5 | #include <sys/time.h> | ||
6 | #include <string.h> | ||
7 | |||
8 | Bu::Speedometer::Speedometer( int64_t iBucketMs, int32_t iBucketCount ) : | ||
9 | aiBucket( NULL ), | ||
10 | iTotal( 0 ), | ||
11 | iCapacity( iBucketCount ), | ||
12 | iFill( 0 ), | ||
13 | iStart( 0 ), | ||
14 | iCurrent( 0 ), | ||
15 | iBucketMs( iBucketMs ), | ||
16 | iStartTime( -1 ), | ||
17 | iWindowSizeMs( iBucketMs*iBucketCount ), | ||
18 | iLastUpdate( -1 ) | ||
19 | { | ||
20 | aiBucket = new uint32_t[iCapacity]; | ||
21 | memset( aiBucket, 0, sizeof(uint32_t)*iCapacity ); | ||
22 | } | ||
23 | |||
24 | Bu::Speedometer::~Speedometer() | ||
25 | { | ||
26 | delete[] aiBucket; | ||
27 | aiBucket = NULL; | ||
28 | } | ||
29 | |||
30 | void Bu::Speedometer::addEvent() | ||
31 | { | ||
32 | Bu::MutexLocker l( mLock ); | ||
33 | int64_t iNow = getCurrentTime(); | ||
34 | _updateBuckets( iNow ); | ||
35 | if( iStartTime < 0 ) | ||
36 | { | ||
37 | iStartTime = iNow; | ||
38 | iFill = 1; | ||
39 | aiBucket[iCurrent] = 1; | ||
40 | iTotal = 1; | ||
41 | } | ||
42 | else | ||
43 | { | ||
44 | aiBucket[iCurrent]++; | ||
45 | iTotal++; | ||
46 | } | ||
47 | iLastUpdate = iNow; | ||
48 | } | ||
49 | |||
50 | void Bu::Speedometer::debug() | ||
51 | { | ||
52 | Bu::MutexLocker l( mLock ); | ||
53 | Bu::print("%1 of %2: %3:%4: "). | ||
54 | arg( iFill ).arg( iCapacity ).arg( iStart ).arg( iCurrent ); | ||
55 | for( int j = 0; j < iFill; j++ ) | ||
56 | { | ||
57 | Bu::print("%1 | ").arg( aiBucket[(j+iStart)%iCapacity] ); | ||
58 | } | ||
59 | Bu::println(" total = %1").arg( iTotal ); | ||
60 | } | ||
61 | |||
62 | void Bu::Speedometer::_updateBuckets( int64_t iNow ) | ||
63 | { | ||
64 | if( iNow > iLastUpdate+iWindowSizeMs ) | ||
65 | { | ||
66 | iLastUpdate = iStartTime = -1; | ||
67 | iFill = 0; | ||
68 | iStart = iCurrent = 0; | ||
69 | aiBucket[iCurrent] = 0; | ||
70 | iTotal = 0; | ||
71 | } | ||
72 | else | ||
73 | { | ||
74 | int64_t iSkip = (iNow-(iStartTime+iBucketMs*iFill)); | ||
75 | if( iSkip < 0 ) | ||
76 | return; | ||
77 | iSkip = (iSkip/iBucketMs) + ((iSkip%iBucketMs)?(1):(0)); | ||
78 | |||
79 | for( int64_t j = 0; j < iSkip; j++ ) | ||
80 | { | ||
81 | iCurrent = (iCurrent+1)%iCapacity; | ||
82 | if( iFill < iCapacity ) | ||
83 | { | ||
84 | iFill++; | ||
85 | } | ||
86 | else | ||
87 | { | ||
88 | iTotal -= aiBucket[iStart]; | ||
89 | aiBucket[iStart] = 0; | ||
90 | iStart = (iStart+1)%iCapacity; | ||
91 | iStartTime += iBucketMs; | ||
92 | } | ||
93 | } | ||
94 | } | ||
95 | } | ||
96 | |||
97 | double Bu::Speedometer::getSpeed() | ||
98 | { | ||
99 | Bu::MutexLocker l( mLock ); | ||
100 | _updateBuckets( getCurrentTime() ); | ||
101 | |||
102 | if( iStartTime < 0 ) | ||
103 | return 0.0; | ||
104 | |||
105 | return (double)iTotal / (double)(iFill*iBucketMs); | ||
106 | } | ||
107 | |||
108 | int32_t Bu::Speedometer::getTotalEvents() | ||
109 | { | ||
110 | Bu::MutexLocker l( mLock ); | ||
111 | return iTotal; | ||
112 | } | ||
113 | |||
114 | int64_t Bu::Speedometer::getCurrentTime() const | ||
115 | { | ||
116 | struct timeval tv; | ||
117 | gettimeofday( &tv, NULL ); | ||
118 | return tv.tv_sec*1000 + tv.tv_usec/1000; | ||
119 | } | ||
120 | |||
diff --git a/src/unstable/speedometer.h b/src/unstable/speedometer.h new file mode 100644 index 0000000..84d21ed --- /dev/null +++ b/src/unstable/speedometer.h | |||
@@ -0,0 +1,43 @@ | |||
1 | #ifndef BU_SPEEDOMETER_H | ||
2 | #define BU_SPEEDOMETER_H | ||
3 | |||
4 | #include "bu/mutex.h" | ||
5 | |||
6 | #include <stdint.h> | ||
7 | |||
8 | namespace Bu | ||
9 | { | ||
10 | class Speedometer | ||
11 | { | ||
12 | public: | ||
13 | Speedometer( int64_t iBucketMs, int32_t iBucketCount ); | ||
14 | virtual ~Speedometer(); | ||
15 | |||
16 | void addEvent(); | ||
17 | double getSpeed(); | ||
18 | int32_t getTotalEvents(); | ||
19 | void debug(); | ||
20 | |||
21 | private: | ||
22 | void _updateBuckets( int64_t iNow ); | ||
23 | /** | ||
24 | * Gets the current time in milliseconds. | ||
25 | */ | ||
26 | int64_t getCurrentTime() const; | ||
27 | |||
28 | private: | ||
29 | uint32_t *aiBucket; | ||
30 | uint32_t iTotal; | ||
31 | int32_t iCapacity; | ||
32 | int32_t iFill; | ||
33 | int32_t iStart; | ||
34 | int32_t iCurrent; | ||
35 | int64_t iBucketMs; | ||
36 | int64_t iStartTime; | ||
37 | int64_t iWindowSizeMs; | ||
38 | int64_t iLastUpdate; | ||
39 | mutable Bu::Mutex mLock; | ||
40 | }; | ||
41 | } | ||
42 | |||
43 | #endif | ||