|
|
|
// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
|
|
|
|
// This source code is licensed under both the GPLv2 (found in the
|
|
|
|
// COPYING file in the root directory) and Apache 2.0 License
|
|
|
|
// (found in the LICENSE.Apache file in the root directory).
|
|
|
|
//
|
|
|
|
// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
|
|
// found in the LICENSE file. See the AUTHORS file for names of contributors.
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
#include "rocksdb/statistics.h"
|
|
|
|
|
|
|
|
#include <cassert>
|
|
|
|
#include <string>
|
|
|
|
#include <vector>
|
|
|
|
#include <map>
|
|
|
|
#include <mutex>
|
|
|
|
|
|
|
|
namespace ROCKSDB_NAMESPACE {
|
|
|
|
|
|
|
|
class HistogramBucketMapper {
|
|
|
|
public:
|
|
|
|
|
|
|
|
HistogramBucketMapper();
|
|
|
|
|
|
|
|
// converts a value to the bucket index.
|
|
|
|
size_t IndexForValue(uint64_t value) const;
|
|
|
|
// number of buckets required.
|
|
|
|
|
|
|
|
size_t BucketCount() const {
|
|
|
|
return bucketValues_.size();
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t LastValue() const {
|
|
|
|
return maxBucketValue_;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t FirstValue() const {
|
|
|
|
return minBucketValue_;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t BucketLimit(const size_t bucketNumber) const {
|
|
|
|
assert(bucketNumber < BucketCount());
|
|
|
|
return bucketValues_[bucketNumber];
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
std::vector<uint64_t> bucketValues_;
|
|
|
|
uint64_t maxBucketValue_;
|
|
|
|
uint64_t minBucketValue_;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct HistogramStat {
|
|
|
|
HistogramStat();
|
|
|
|
~HistogramStat() {}
|
|
|
|
|
|
|
|
HistogramStat(const HistogramStat&) = delete;
|
|
|
|
HistogramStat& operator=(const HistogramStat&) = delete;
|
|
|
|
|
|
|
|
void Clear();
|
|
|
|
bool Empty() const;
|
|
|
|
void Add(uint64_t value);
|
|
|
|
void Merge(const HistogramStat& other);
|
|
|
|
|
|
|
|
inline uint64_t min() const { return min_.load(std::memory_order_relaxed); }
|
|
|
|
inline uint64_t max() const { return max_.load(std::memory_order_relaxed); }
|
|
|
|
inline uint64_t num() const { return num_.load(std::memory_order_relaxed); }
|
|
|
|
inline uint64_t sum() const { return sum_.load(std::memory_order_relaxed); }
|
|
|
|
inline uint64_t sum_squares() const {
|
|
|
|
return sum_squares_.load(std::memory_order_relaxed);
|
|
|
|
}
|
|
|
|
inline uint64_t bucket_at(size_t b) const {
|
|
|
|
return buckets_[b].load(std::memory_order_relaxed);
|
|
|
|
}
|
|
|
|
|
|
|
|
double Median() const;
|
|
|
|
double Percentile(double p) const;
|
|
|
|
double Average() const;
|
|
|
|
double StandardDeviation() const;
|
|
|
|
void Data(HistogramData* const data) const;
|
|
|
|
std::string ToString() const;
|
|
|
|
|
|
|
|
// To be able to use HistogramStat as thread local variable, it
|
|
|
|
// cannot have dynamic allocated member. That's why we're
|
|
|
|
// using manually values from BucketMapper
|
|
|
|
std::atomic_uint_fast64_t min_;
|
|
|
|
std::atomic_uint_fast64_t max_;
|
|
|
|
std::atomic_uint_fast64_t num_;
|
|
|
|
std::atomic_uint_fast64_t sum_;
|
|
|
|
std::atomic_uint_fast64_t sum_squares_;
|
|
|
|
std::atomic_uint_fast64_t buckets_[109]; // 109==BucketMapper::BucketCount()
|
|
|
|
const uint64_t num_buckets_;
|
|
|
|
};
|
|
|
|
|
|
|
|
class Histogram {
|
|
|
|
public:
|
|
|
|
Histogram() {}
|
|
|
|
virtual ~Histogram() {};
|
|
|
|
|
|
|
|
virtual void Clear() = 0;
|
|
|
|
virtual bool Empty() const = 0;
|
|
|
|
virtual void Add(uint64_t value) = 0;
|
|
|
|
virtual void Merge(const Histogram&) = 0;
|
|
|
|
|
|
|
|
virtual std::string ToString() const = 0;
|
|
|
|
virtual const char* Name() const = 0;
|
|
|
|
virtual uint64_t min() const = 0;
|
|
|
|
virtual uint64_t max() const = 0;
|
|
|
|
virtual uint64_t num() const = 0;
|
|
|
|
virtual double Median() const = 0;
|
|
|
|
virtual double Percentile(double p) const = 0;
|
|
|
|
virtual double Average() const = 0;
|
|
|
|
virtual double StandardDeviation() const = 0;
|
|
|
|
virtual void Data(HistogramData* const data) const = 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
class HistogramImpl : public Histogram {
|
|
|
|
public:
|
|
|
|
HistogramImpl() { Clear(); }
|
|
|
|
|
|
|
|
HistogramImpl(const HistogramImpl&) = delete;
|
|
|
|
HistogramImpl& operator=(const HistogramImpl&) = delete;
|
|
|
|
|
|
|
|
virtual void Clear() override;
|
|
|
|
virtual bool Empty() const override;
|
|
|
|
virtual void Add(uint64_t value) override;
|
|
|
|
virtual void Merge(const Histogram& other) override;
|
|
|
|
void Merge(const HistogramImpl& other);
|
|
|
|
|
|
|
|
virtual std::string ToString() const override;
|
|
|
|
virtual const char* Name() const override { return "HistogramImpl"; }
|
|
|
|
virtual uint64_t min() const override { return stats_.min(); }
|
|
|
|
virtual uint64_t max() const override { return stats_.max(); }
|
|
|
|
virtual uint64_t num() const override { return stats_.num(); }
|
|
|
|
virtual double Median() const override;
|
|
|
|
virtual double Percentile(double p) const override;
|
|
|
|
virtual double Average() const override;
|
|
|
|
virtual double StandardDeviation() const override;
|
|
|
|
virtual void Data(HistogramData* const data) const override;
|
|
|
|
|
|
|
|
virtual ~HistogramImpl() {}
|
|
|
|
|
|
|
|
inline HistogramStat& TEST_GetStats() { return stats_; }
|
|
|
|
|
|
|
|
private:
|
|
|
|
HistogramStat stats_;
|
|
|
|
std::mutex mutex_;
|
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace ROCKSDB_NAMESPACE
|