common/buffer.cc \
common/code_environment.cc \
common/dout.cc \
+ common/histogram.cc \
common/signal.cc \
common/simple_spin.cc \
common/Thread.cc \
common/fd.h \
common/version.h \
common/hex.h \
+ common/histogram.h \
common/entity_name.h \
common/errno.h \
common/environment.h \
#include <stdint.h>
#include <include/utime.h>
#include "common/Mutex.h"
-#include "include/histogram.h"
+#include "common/histogram.h"
#include "include/xlist.h"
#include "msg/Message.h"
#include "include/memory.h"
--- /dev/null
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2011 New Dream Network
+ *
+ * This is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software
+ * Foundation. See file COPYING.
+ *
+ */
+
+#include "common/histogram.h"
+#include "common/Formatter.h"
+
+// -- pow2_hist_t --
+void pow2_hist_t::dump(Formatter *f) const
+{
+ f->open_array_section("histogram");
+ for (std::vector<int32_t>::const_iterator p = h.begin(); p != h.end(); ++p)
+ f->dump_int("count", *p);
+ f->close_section();
+ f->dump_int("upper_bound", upper_bound());
+}
+
+void pow2_hist_t::encode(bufferlist& bl) const
+{
+ ENCODE_START(1, 1, bl);
+ ::encode(h, bl);
+ ENCODE_FINISH(bl);
+}
+
+void pow2_hist_t::decode(bufferlist::iterator& p)
+{
+ DECODE_START(1, p);
+ ::decode(h, p);
+ DECODE_FINISH(p);
+}
+
+void pow2_hist_t::generate_test_instances(std::list<pow2_hist_t*>& ls)
+{
+ ls.push_back(new pow2_hist_t);
+ ls.push_back(new pow2_hist_t);
+ ls.back()->h.push_back(1);
+ ls.back()->h.push_back(3);
+ ls.back()->h.push_back(0);
+ ls.back()->h.push_back(2);
+}
--- /dev/null
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+/*
+ * Ceph - scalable distributed file system
+ *
+ * This is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software
+ * Foundation. See file COPYING.
+ * Copyright 2013 Inktank
+ */
+
+#ifndef CEPH_HISTOGRAM_H
+#define CEPH_HISTOGRAM_H
+
+#include <vector>
+#include <list>
+
+#include "include/encoding.h"
+
+namespace ceph {
+ class Formatter;
+}
+
+/**
+ * power of 2 histogram
+ */
+struct pow2_hist_t { //
+ /**
+ * histogram
+ *
+ * bin size is 2^index
+ * value is count of elements that are <= the current bin but > the previous bin.
+ */
+ std::vector<int32_t> h;
+
+private:
+ /// expand to at least another's size
+ void _expand_to(unsigned s) {
+ if (s > h.size())
+ h.resize(s, 0);
+ }
+ /// drop useless trailing 0's
+ void _contract() {
+ unsigned p = h.size();
+ while (p > 0 && h[p-1] == 0)
+ --p;
+ h.resize(p);
+ }
+
+public:
+ void clear() {
+ h.clear();
+ }
+ void set_bin(int bin, int32_t count) {
+ _expand_to(bin + 1);
+ h[bin] = count;
+ _contract();
+ }
+
+ void add(int32_t v) {
+ int bin = calc_bits_of(v);
+ _expand_to(bin + 1);
+ h[bin]++;
+ _contract();
+ }
+
+ static int calc_bits_of(int t) {
+ int b = 0;
+ while (t > 0) {
+ t = t >> 1;
+ b++;
+ }
+ return b;
+ }
+
+ /// get a value's position in the histogram.
+ ///
+ /// positions are represented as values in the range [0..1000000]
+ /// (millionths on the unit interval).
+ ///
+ /// @param v [in] value (non-negative)
+ /// @param lower [out] pointer to lower-bound (0..1000000)
+ /// @param upper [out] pointer to the upper bound (0..1000000)
+ int get_position_micro(int32_t v, unsigned *lower, unsigned *upper) {
+ if (v < 0)
+ return -1;
+ unsigned bin = calc_bits_of(v);
+ unsigned lower_sum = 0, upper_sum = 0, total = 0;
+ for (unsigned i=0; i<h.size(); ++i) {
+ if (i <= bin)
+ upper_sum += h[i];
+ if (i < bin)
+ lower_sum += h[i];
+ total += h[i];
+ }
+ *lower = lower_sum * 1000000 / total;
+ *upper = upper_sum * 1000000 / total;
+ return 0;
+ }
+
+ void add(const pow2_hist_t& o) {
+ _expand_to(o.h.size());
+ for (unsigned p = 0; p < o.h.size(); ++p)
+ h[p] += o.h[p];
+ _contract();
+ }
+ void sub(const pow2_hist_t& o) {
+ _expand_to(o.h.size());
+ for (unsigned p = 0; p < o.h.size(); ++p)
+ h[p] -= o.h[p];
+ _contract();
+ }
+
+ int32_t upper_bound() const {
+ return 1 << h.size();
+ }
+
+ void dump(Formatter *f) const;
+ void encode(bufferlist &bl) const;
+ void decode(bufferlist::iterator &bl);
+ static void generate_test_instances(std::list<pow2_hist_t*>& o);
+};
+WRITE_CLASS_ENCODER(pow2_hist_t)
+
+#endif /* CEPH_HISTOGRAM_H */
include/filepath.h \
include/frag.h \
include/hash.h \
- include/histogram.h \
include/intarith.h \
include/interval_set.h \
include/int_types.h \
+++ /dev/null
-// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
-// vim: ts=8 sw=2 smarttab
-/*
- * Ceph - scalable distributed file system
- *
- * This is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1, as published by the Free Software
- * Foundation. See file COPYING.
- * Copyright 2013 Inktank
- */
-
-#ifndef HISTOGRAM_H_
-#define HISTOGRAM_H_
-
-/**
- * power of 2 histogram
- */
-struct pow2_hist_t { //
- /**
- * histogram
- *
- * bin size is 2^index
- * value is count of elements that are <= the current bin but > the previous bin.
- */
- vector<int32_t> h;
-
-private:
- /// expand to at least another's size
- void _expand_to(unsigned s) {
- if (s > h.size())
- h.resize(s, 0);
- }
- /// drop useless trailing 0's
- void _contract() {
- unsigned p = h.size();
- while (p > 0 && h[p-1] == 0)
- --p;
- h.resize(p);
- }
-
-public:
- void clear() {
- h.clear();
- }
- void set_bin(int bin, int32_t count) {
- _expand_to(bin + 1);
- h[bin] = count;
- _contract();
- }
-
- static int calc_bits_of(int t) {
- int b = 0;
- while (t > 0) {
- t = t >> 1;
- b++;
- }
- return b;
- }
-
- /// get a value's position in the histogram.
- ///
- /// positions are represented as values in the range [0..1000000]
- /// (millionths on the unit interval).
- ///
- /// @param v [in] value (non-negative)
- /// @param lower [out] pointer to lower-bound (0..1000000)
- /// @param upper [out] pointer to the upper bound (0..1000000)
- int get_position_micro(int32_t v, unsigned *lower, unsigned *upper) {
- if (v < 0)
- return -ERANGE;
- unsigned bin = calc_bits_of(v);
- unsigned lower_sum = 0, upper_sum = 0, total = 0;
- for (unsigned i=0; i<h.size(); ++i) {
- if (i <= bin)
- upper_sum += h[i];
- if (i < bin)
- lower_sum += h[i];
- total += h[i];
- }
- *lower = lower_sum * 1000000 / total;
- *upper = upper_sum * 1000000 / total;
- return 0;
- }
-
- void add(const pow2_hist_t& o) {
- _expand_to(o.h.size());
- for (unsigned p = 0; p < o.h.size(); ++p)
- h[p] += o.h[p];
- _contract();
- }
- void sub(const pow2_hist_t& o) {
- _expand_to(o.h.size());
- for (unsigned p = 0; p < o.h.size(); ++p)
- h[p] -= o.h[p];
- _contract();
- }
-
- int32_t upper_bound() const {
- return 1 << h.size();
- }
-
- void dump(Formatter *f) const;
- void encode(bufferlist &bl) const;
- void decode(bufferlist::iterator &bl);
- static void generate_test_instances(std::list<pow2_hist_t*>& o);
-};
-WRITE_CLASS_ENCODER(pow2_hist_t)
-
-#endif /* HISTOGRAM_H_ */
#include "PaxosService.h"
#include "include/types.h"
#include "include/utime.h"
-#include "include/histogram.h"
+#include "common/histogram.h"
#include "msg/Messenger.h"
#include "common/config.h"
#include "mon/MonitorDBStore.h"
o.push_back(new request_redirect_t(loc));
}
-// -- pow2_hist_t --
-void pow2_hist_t::dump(Formatter *f) const
-{
- f->open_array_section("histogram");
- for (vector<int>::const_iterator p = h.begin(); p != h.end(); ++p)
- f->dump_int("count", *p);
- f->close_section();
- f->dump_int("upper_bound", upper_bound());
-}
-
-void pow2_hist_t::encode(bufferlist& bl) const
-{
- ENCODE_START(1, 1, bl);
- ::encode(h, bl);
- ENCODE_FINISH(bl);
-}
-
-void pow2_hist_t::decode(bufferlist::iterator& p)
-{
- DECODE_START(1, p);
- ::decode(h, p);
- DECODE_FINISH(p);
-}
-
-void pow2_hist_t::generate_test_instances(list<pow2_hist_t*>& ls)
-{
- ls.push_back(new pow2_hist_t);
- ls.push_back(new pow2_hist_t);
- ls.back()->h.push_back(1);
- ls.back()->h.push_back(3);
- ls.back()->h.push_back(0);
- ls.back()->h.push_back(2);
-}
-
void objectstore_perf_stat_t::dump(Formatter *f) const
{
f->dump_unsigned("commit_latency_ms", filestore_commit_latency);
#include "include/types.h"
#include "include/utime.h"
#include "include/CompatSet.h"
-#include "include/histogram.h"
+#include "common/histogram.h"
#include "include/interval_set.h"
#include "common/Formatter.h"
#include "common/bloom_filter.hpp"
unittest_bloom_filter_LDADD = $(UNITTEST_LDADD) $(CEPH_GLOBAL)
check_PROGRAMS += unittest_bloom_filter
+unittest_histogram_SOURCES = test/common/histogram.cc
+unittest_histogram_CXXFLAGS = $(UNITTEST_CXXFLAGS)
+unittest_histogram_LDADD = $(UNITTEST_LDADD) $(CEPH_GLOBAL)
+check_PROGRAMS += unittest_histogram
+
unittest_str_map_SOURCES = test/common/test_str_map.cc
unittest_str_map_CXXFLAGS = $(UNITTEST_CXXFLAGS)
unittest_str_map_LDADD = $(UNITTEST_LDADD) $(CEPH_GLOBAL)
--- /dev/null
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2014 Inktank <info@inktank.com>
+ *
+ * LGPL2.1 (see COPYING-LGPL2.1) or later
+ */
+
+#include <iostream>
+#include <gtest/gtest.h>
+
+#include "common/histogram.h"
+#include "include/stringify.h"
+
+TEST(Histogram, Basic) {
+ pow2_hist_t h;
+
+ h.add(0);
+ h.add(0);
+ h.add(0);
+ ASSERT_EQ(3, h.h[0]);
+ ASSERT_EQ(1u, h.h.size());
+
+ h.add(1);
+ ASSERT_EQ(3, h.h[0]);
+ ASSERT_EQ(1, h.h[1]);
+ ASSERT_EQ(2u, h.h.size());
+
+ h.add(2);
+ h.add(2);
+ ASSERT_EQ(3, h.h[0]);
+ ASSERT_EQ(1, h.h[1]);
+ ASSERT_EQ(2, h.h[2]);
+ ASSERT_EQ(3u, h.h.size());
+}
+
+TEST(Histogram, Set) {
+ pow2_hist_t h;
+ h.set_bin(0, 12);
+ h.set_bin(2, 12);
+ ASSERT_EQ(12, h.h[0]);
+ ASSERT_EQ(0, h.h[1]);
+ ASSERT_EQ(12, h.h[2]);
+ ASSERT_EQ(3u, h.h.size());
+}
+
+TEST(Histogram, Position) {
+ {
+ pow2_hist_t h;
+ unsigned lb, ub;
+ h.add(0);
+ ASSERT_EQ(-1, h.get_position_micro(-20, &lb, &ub));
+ }
+ {
+ pow2_hist_t h;
+ h.add(0);
+ unsigned lb, ub;
+ h.get_position_micro(0, &lb, &ub);
+ ASSERT_EQ(0, lb);
+ ASSERT_EQ(1000000, ub);
+ h.add(0);
+ h.add(0);
+ h.add(0);
+ h.get_position_micro(0, &lb, &ub);
+ ASSERT_EQ(0, lb);
+ ASSERT_EQ(1000000, ub);
+ }
+ {
+ pow2_hist_t h;
+ h.add(1);
+ h.add(1);
+ unsigned lb, ub;
+ h.get_position_micro(0, &lb, &ub);
+ ASSERT_EQ(0, lb);
+ ASSERT_EQ(0, ub);
+ h.add(0);
+ h.get_position_micro(0, &lb, &ub);
+ ASSERT_EQ(0, lb);
+ ASSERT_EQ(333333, ub);
+ h.get_position_micro(1, &lb, &ub);
+ ASSERT_EQ(333333, lb);
+ ASSERT_EQ(1000000, ub);
+ }
+ {
+ pow2_hist_t h;
+ h.add(1);
+ h.add(10);
+ unsigned lb, ub;
+ h.get_position_micro(4, &lb, &ub);
+ ASSERT_EQ(500000, lb);
+ ASSERT_EQ(500000, ub);
+ }
+}
#include "crush/CrushWrapper.h"
TYPE_NOCOPY(CrushWrapper)
-#include "include/histogram.h"
+#include "common/histogram.h"
TYPE(pow2_hist_t)
#include "osd/osd_types.h"