summaryrefslogtreecommitdiff
path: root/util/histogram.cpp
diff options
context:
space:
mode:
authorAlberto Lerner <alerner@10gen.com>2010-06-02 10:53:51 -0400
committerAlberto Lerner <alerner@10gen.com>2010-06-02 10:53:51 -0400
commit701240d1baa2303b871e232371e19fcb7d36e71f (patch)
treefb512fcbf6d53c0c37c732aef6a196873898079c /util/histogram.cpp
parent783bf1e4d7f5f9caadf73233df59f6672b47120f (diff)
downloadmongo-701240d1baa2303b871e232371e19fcb7d36e71f.tar.gz
Initial support for histograms (eg. cumulative stats)
Diffstat (limited to 'util/histogram.cpp')
-rw-r--r--util/histogram.cpp121
1 files changed, 121 insertions, 0 deletions
diff --git a/util/histogram.cpp b/util/histogram.cpp
new file mode 100644
index 00000000000..45bc9a8ddd2
--- /dev/null
+++ b/util/histogram.cpp
@@ -0,0 +1,121 @@
+// histogram.cc
+
+/**
+* Copyright (C) 2010 10gen Inc.
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Affero General Public License, version 3,
+* as published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Affero General Public License for more details.
+*
+* You should have received a copy of the GNU Affero General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <limits>
+#include <sstream>
+#include <iomanip>
+
+#include "histogram.h"
+
+namespace mongo {
+
+ using std::ostringstream;
+ using std::setfill;
+ using std::setw;
+
+ Histogram::Histogram( const Options& opts )
+ : _initialValue( opts.initialValue )
+ , _numBuckets( opts.numBuckets )
+ , _boundaries( new uint32_t[_numBuckets] )
+ , _buckets( new uint64_t[_numBuckets] ){
+
+ // TODO more sanity checks
+ // + not too few buckets
+ // + initialBucket and bucketSize fit within 32 bit ints
+
+ // _boundaries store the maximum value falling in that bucket.
+ _boundaries[0] = _initialValue + opts.bucketSize;
+ for ( uint32_t i = 1; i < _numBuckets - 1; i++ ){
+ _boundaries[i] = _boundaries[ i-1 ] + opts.bucketSize;
+ }
+ _boundaries[ _numBuckets-1 ] = std::numeric_limits<uint32_t>::max();
+
+ for ( uint32_t i = 0; i < _numBuckets; i++ ) {
+ _buckets[i] = 0;
+ }
+ }
+
+ Histogram::~Histogram() {
+ delete [] _boundaries;
+ delete [] _buckets;
+ }
+
+ void Histogram::insert( uint32_t element ){
+ if ( element < _initialValue) return;
+
+ _buckets[ findBucket(element) ] += 1;
+ }
+
+ string Histogram::toHTML() const{
+ uint64_t max = 0;
+ for ( uint32_t i = 0; i < _numBuckets; i++ ){
+ if ( _buckets[i] > max ){
+ max = _buckets[i];
+ }
+ }
+ if ( max == 0 ) {
+ return "histogram is empty\n";
+ }
+
+ // normalize buckets to max
+ const int maxBar = 20;
+ ostringstream ss;
+ for ( uint32_t i = 0; i < _numBuckets; i++ ){
+ int barSize = _buckets[i] * maxBar / max;
+ ss << string( barSize,'*' )
+ << setfill(' ') << setw( maxBar-barSize + 12 )
+ << _boundaries[i] << '\n';
+ }
+
+ return ss.str();
+ }
+
+ uint64_t Histogram::getCount( uint32_t bucket ) const {
+ if ( bucket >= _numBuckets ) return 0;
+
+ return _buckets[ bucket ];
+ }
+
+ uint32_t Histogram::getBoundary( uint32_t bucket ) const {
+ if ( bucket >= _numBuckets ) return 0;
+
+ return _boundaries[ bucket ];
+ }
+
+ uint32_t Histogram::getBucketsNum() const {
+ return _numBuckets;
+ }
+
+ uint32_t Histogram::findBucket( uint32_t element ) const{
+ // TODO assert not too small a value?
+
+ uint32_t low = 0;
+ uint32_t high = _numBuckets - 1;
+ while ( low < high ){
+ // low + ( (high - low) / 2 );
+ uint32_t mid = ( low + high ) >> 1;
+ if ( element > _boundaries[ mid ] ){
+ low = mid + 1;
+ } else {
+ high = mid;
+ }
+ }
+ return low;
+ }
+
+} // namespace mongo