In particular, look at the steady state decay. (i.e. a counter that is
continuously "refilled".)
Signed-off-by: Patrick Donnelly <pdonnell@redhat.com>
(cherry picked from commit
ce151e3e472da75d707fb12ab8c7c32cb65c9248)
add_ceph_unittest(unittest_lockdep)
target_link_libraries(unittest_lockdep ceph-common)
+# unittest_counter
+add_executable(unittest_counter
+ test_counter.cc)
+add_ceph_unittest(unittest_counter)
+target_link_libraries(unittest_counter ceph-common)
+
# FreeBSD only has shims to support NUMA, no functional code.
if(LINUX)
# unittest_numa
--- /dev/null
+#include "common/DecayCounter.h"
+
+#include <gtest/gtest.h>
+
+#include <list>
+#include <cmath>
+
+TEST(DecayCounter, steady)
+{
+ static const double duration = 2.0;
+ static const double max = 2048.0;
+ static const double rate = 3.5;
+
+ DecayCounter d{DecayRate{rate}};
+ d.hit(max);
+ const auto start = DecayCounter::clock::now();
+ double total = 0.0;
+ while (1) {
+ const auto now = DecayCounter::clock::now();
+ auto el = std::chrono::duration<double>(now-start);
+ if (el.count() > duration) {
+ break;
+ }
+
+ double v = d.get();
+ double diff = max-v;
+ if (diff > 0.0) {
+ d.hit(diff);
+ total += diff;
+ }
+ }
+
+ /* Decay function: dN/dt = -λM where λ = ln(0.5)/rate
+ * (where M is the maximum value of the counter, not varying with time.)
+ * Integrating over t: N = -λMt (+c)
+ */
+ double expected = -1*std::log(0.5)/rate*max*duration;
+ std::cerr << "t " << total << " e " << expected << std::endl;
+ ASSERT_LT(std::abs(total-expected)/expected, 0.01);
+}
+++ /dev/null
-
-#include "common/DecayCounter.h"
-
-#include <list>
-
-#include <unistd.h>
-using namespace std;
-
-struct RealCounter {
-public:
- list<int> hits;
-
- void hit(int ms) {
- hits.push_back(ms);
- }
-
- int get(double hl, int now) {
- trim(now-hl);
- return hits.size();
- }
-
- void trim(int to) {
- while (!hits.empty() &&
- hits.front() < to)
- hits.pop_front();
- }
-
-
-};
-
-int main(int argc, char **argv)
-{
- int target;
- double hl = atof(argv[1]);
- cerr << "halflife " << hl << endl;
-
- DecayCounter dc(hl);
- RealCounter rc;
-
- DecayCounter::time now = DecayCounter::clock::now();
-
- for (int ms=0; ms < 300*1000; ms++) {
- if (ms % 30000 == 0) {
- target = 1 + (rand() % 10) * 10;
- if (ms > 200000) target = 0;
- }
-
- if (target &&
- (rand() % (1000/target) == 0)) {
- dc.hit();
- rc.hit(ms);
- }
-
- if (ms % 500 == 0) dc.get(now);
- if (ms % 100 == 0) {
- //dc.get(now);
- DecayCounter o = dc;
- cout << ms << "\t"
- << target*hl << "\t"
- << rc.get(hl*1000, ms) << "\t"
- << o.get(now) << "\t"
- << dc.val << "\t"
- // << dc.delta << "\t"
- << o.get_last_vel() << "\t"
- << o.get_last() + o.get_last_vel() << "\t"
- << endl;
- }
-
- usleep(1);
- now = DecayCounter::clock::now();
- }
-
-}