diff options
author | Mike Buland <mbuland@penny-arcade.com> | 2018-07-02 11:34:44 -0700 |
---|---|---|
committer | Mike Buland <mbuland@penny-arcade.com> | 2018-07-02 11:34:44 -0700 |
commit | 74973a93594e4150a827459708895577a795036b (patch) | |
tree | 9faff0701bf458144c58f9b9d29ce845dd132aeb /src/unstable | |
parent | 9bcbc8f919fc1c779d3b9c649dcbe3606fdbed32 (diff) | |
download | libbu++-74973a93594e4150a827459708895577a795036b.tar.gz libbu++-74973a93594e4150a827459708895577a795036b.tar.bz2 libbu++-74973a93594e4150a827459708895577a795036b.tar.xz libbu++-74973a93594e4150a827459708895577a795036b.zip |
Added a threadsafe speedometer class.
Diffstat (limited to 'src/unstable')
-rw-r--r-- | src/unstable/speedometer.cpp | 120 | ||||
-rw-r--r-- | src/unstable/speedometer.h | 43 |
2 files changed, 163 insertions, 0 deletions
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 | ||