YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/Users/deen/code/yugabyte-db/src/yb/util/striped64-test.cc
Line
Count
Source
1
// Licensed to the Apache Software Foundation (ASF) under one
2
// or more contributor license agreements.  See the NOTICE file
3
// distributed with this work for additional information
4
// regarding copyright ownership.  The ASF licenses this file
5
// to you under the Apache License, Version 2.0 (the
6
// "License"); you may not use this file except in compliance
7
// with the License.  You may obtain a copy of the License at
8
//
9
//   http://www.apache.org/licenses/LICENSE-2.0
10
//
11
// Unless required by applicable law or agreed to in writing,
12
// software distributed under the License is distributed on an
13
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
// KIND, either express or implied.  See the License for the
15
// specific language governing permissions and limitations
16
// under the License.
17
//
18
// The following only applies to changes made to this file as part of YugaByte development.
19
//
20
// Portions Copyright (c) YugaByte, Inc.
21
//
22
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
23
// in compliance with the License.  You may obtain a copy of the License at
24
//
25
// http://www.apache.org/licenses/LICENSE-2.0
26
//
27
// Unless required by applicable law or agreed to in writing, software distributed under the License
28
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
29
// or implied.  See the License for the specific language governing permissions and limitations
30
// under the License.
31
//
32
#include <memory>
33
34
#include <glog/logging.h>
35
#include <gtest/gtest.h>
36
37
#include "yb/util/monotime.h"
38
#include "yb/util/status_log.h"
39
#include "yb/util/striped64.h"
40
#include "yb/util/test_util.h"
41
#include "yb/util/thread.h"
42
43
namespace yb {
44
45
// These flags are used by the multi-threaded tests, can be used for microbenchmarking.
46
DEFINE_int32(num_operations, 10*1000, "Number of operations to perform");
47
DEFINE_int32(num_threads, 2, "Number of worker threads");
48
49
// Test some basic operations
50
1
TEST(Striped64Test, TestBasic) {
51
1
  LongAdder adder;
52
1
  ASSERT_EQ(adder.Value(), 0);
53
1
  adder.IncrementBy(100);
54
1
  ASSERT_EQ(adder.Value(), 100);
55
1
  adder.Increment();
56
1
  ASSERT_EQ(adder.Value(), 101);
57
1
  adder.Decrement();
58
1
  ASSERT_EQ(adder.Value(), 100);
59
1
  adder.IncrementBy(-200);
60
1
  ASSERT_EQ(adder.Value(), -100);
61
1
  adder.Reset();
62
1
  ASSERT_EQ(adder.Value(), 0);
63
1
}
64
65
template <class Adder>
66
class MultiThreadTest {
67
 public:
68
  typedef std::vector<scoped_refptr<Thread> > thread_vec_t;
69
70
  MultiThreadTest(int64_t num_operations, int64_t num_threads)
71
      : num_operations_(num_operations),
72
4
        num_threads_(num_threads) {
73
4
  }
_ZN2yb15MultiThreadTestINS_10BasicAdderEEC2Exx
Line
Count
Source
72
2
        num_threads_(num_threads) {
73
2
  }
_ZN2yb15MultiThreadTestINS_9LongAdderEEC2Exx
Line
Count
Source
72
2
        num_threads_(num_threads) {
73
2
  }
74
75
6
  void IncrementerThread(const int64_t num) {
76
55.9k
    for (int i = 0; i < num; i++) {
77
55.9k
      adder_.Increment();
78
55.9k
    }
79
6
  }
_ZN2yb15MultiThreadTestINS_10BasicAdderEE17IncrementerThreadEx
Line
Count
Source
75
3
  void IncrementerThread(const int64_t num) {
76
29.9k
    for (int i = 0; i < num; i++) {
77
29.9k
      adder_.Increment();
78
29.9k
    }
79
3
  }
_ZN2yb15MultiThreadTestINS_9LongAdderEE17IncrementerThreadEx
Line
Count
Source
75
3
  void IncrementerThread(const int64_t num) {
76
26.0k
    for (int i = 0; i < num; i++) {
77
26.0k
      adder_.Increment();
78
26.0k
    }
79
3
  }
80
81
6
  void DecrementerThread(const int64_t num) {
82
56.4k
    for (int i = 0; i < num; i++) {
83
56.4k
      adder_.Decrement();
84
56.4k
    }
85
6
  }
_ZN2yb15MultiThreadTestINS_10BasicAdderEE17DecrementerThreadEx
Line
Count
Source
81
3
  void DecrementerThread(const int64_t num) {
82
29.9k
    for (int i = 0; i < num; i++) {
83
29.9k
      adder_.Decrement();
84
29.9k
    }
85
3
  }
_ZN2yb15MultiThreadTestINS_9LongAdderEE17DecrementerThreadEx
Line
Count
Source
81
3
  void DecrementerThread(const int64_t num) {
82
26.4k
    for (int i = 0; i < num; i++) {
83
26.4k
      adder_.Decrement();
84
26.4k
    }
85
3
  }
86
87
4
  void Run() {
88
    // Increment
89
10
    for (int i = 0; i < num_threads_; i++) {
90
6
      scoped_refptr<Thread> ref;
91
6
      CHECK_OK(
92
6
          Thread::Create("Striped64", "Incrementer", &MultiThreadTest::IncrementerThread, this,
93
6
                         num_operations_, &ref));
94
6
      threads_.push_back(ref);
95
6
    }
96
6
    for (const scoped_refptr<Thread> &t : threads_) {
97
6
      t->Join();
98
6
    }
99
4
    ASSERT_EQ(num_threads_*num_operations_, adder_.Value());
100
4
    threads_.clear();
101
102
    // Decrement back to zero
103
10
    for (int i = 0; i < num_threads_; i++) {
104
6
      scoped_refptr<Thread> ref;
105
6
      CHECK_OK(
106
6
          Thread::Create("Striped64", "Decrementer", &MultiThreadTest::DecrementerThread, this,
107
6
                         num_operations_, &ref));
108
6
      threads_.push_back(ref);
109
6
    }
110
6
    for (const scoped_refptr<Thread> &t : threads_) {
111
6
      t->Join();
112
6
    }
113
4
    ASSERT_EQ(0, adder_.Value());
114
4
  }
_ZN2yb15MultiThreadTestINS_10BasicAdderEE3RunEv
Line
Count
Source
87
2
  void Run() {
88
    // Increment
89
5
    for (int i = 0; i < num_threads_; i++) {
90
3
      scoped_refptr<Thread> ref;
91
3
      CHECK_OK(
92
3
          Thread::Create("Striped64", "Incrementer", &MultiThreadTest::IncrementerThread, this,
93
3
                         num_operations_, &ref));
94
3
      threads_.push_back(ref);
95
3
    }
96
3
    for (const scoped_refptr<Thread> &t : threads_) {
97
3
      t->Join();
98
3
    }
99
2
    ASSERT_EQ(num_threads_*num_operations_, adder_.Value());
100
2
    threads_.clear();
101
102
    // Decrement back to zero
103
5
    for (int i = 0; i < num_threads_; i++) {
104
3
      scoped_refptr<Thread> ref;
105
3
      CHECK_OK(
106
3
          Thread::Create("Striped64", "Decrementer", &MultiThreadTest::DecrementerThread, this,
107
3
                         num_operations_, &ref));
108
3
      threads_.push_back(ref);
109
3
    }
110
3
    for (const scoped_refptr<Thread> &t : threads_) {
111
3
      t->Join();
112
3
    }
113
2
    ASSERT_EQ(0, adder_.Value());
114
2
  }
_ZN2yb15MultiThreadTestINS_9LongAdderEE3RunEv
Line
Count
Source
87
2
  void Run() {
88
    // Increment
89
5
    for (int i = 0; i < num_threads_; i++) {
90
3
      scoped_refptr<Thread> ref;
91
3
      CHECK_OK(
92
3
          Thread::Create("Striped64", "Incrementer", &MultiThreadTest::IncrementerThread, this,
93
3
                         num_operations_, &ref));
94
3
      threads_.push_back(ref);
95
3
    }
96
3
    for (const scoped_refptr<Thread> &t : threads_) {
97
3
      t->Join();
98
3
    }
99
2
    ASSERT_EQ(num_threads_*num_operations_, adder_.Value());
100
2
    threads_.clear();
101
102
    // Decrement back to zero
103
5
    for (int i = 0; i < num_threads_; i++) {
104
3
      scoped_refptr<Thread> ref;
105
3
      CHECK_OK(
106
3
          Thread::Create("Striped64", "Decrementer", &MultiThreadTest::DecrementerThread, this,
107
3
                         num_operations_, &ref));
108
3
      threads_.push_back(ref);
109
3
    }
110
3
    for (const scoped_refptr<Thread> &t : threads_) {
111
3
      t->Join();
112
3
    }
113
2
    ASSERT_EQ(0, adder_.Value());
114
2
  }
115
116
  Adder adder_;
117
118
  int64_t num_operations_;
119
  // This is rounded down to the nearest even number
120
  int64_t num_threads_;
121
  thread_vec_t threads_;
122
};
123
124
// Test adder implemented by a single AtomicInt for comparison
125
class BasicAdder {
126
 public:
127
2
  BasicAdder() : value_(0) {}
128
59.9k
  void IncrementBy(int64_t x) { value_.IncrementBy(x); }
129
29.9k
  inline void Increment() { IncrementBy(1); }
130
29.9k
  inline void Decrement() { IncrementBy(-1); }
131
4
  int64_t Value() { return value_.Load(); }
132
 private:
133
  AtomicInt<int64_t> value_;
134
};
135
136
2
void RunMultiTest(int64_t num_operations, int64_t num_threads) {
137
2
  MonoTime start = MonoTime::Now();
138
2
  MultiThreadTest<BasicAdder> basicTest(num_operations, num_threads);
139
2
  basicTest.Run();
140
2
  MonoTime end1 = MonoTime::Now();
141
2
  MultiThreadTest<LongAdder> test(num_operations, num_threads);
142
2
  test.Run();
143
2
  MonoTime end2 = MonoTime::Now();
144
2
  MonoDelta basic = end1.GetDeltaSince(start);
145
2
  MonoDelta striped = end2.GetDeltaSince(end1);
146
2
  LOG(INFO) << "Basic counter took   " << basic.ToMilliseconds() << "ms.";
147
2
  LOG(INFO) << "Striped counter took " << striped.ToMilliseconds() << "ms.";
148
2
}
149
150
// Compare a single-thread workload. Demonstrates the overhead of LongAdder over AtomicInt.
151
1
TEST(Striped64Test, TestSingleIncrDecr) {
152
1
  OverrideFlagForSlowTests(
153
1
      "num_operations",
154
1
      strings::Substitute("$0", (FLAGS_num_operations * 100)));
155
1
  RunMultiTest(FLAGS_num_operations, 1);
156
1
}
157
158
// Compare a multi-threaded workload. LongAdder should show improvements here.
159
1
TEST(Striped64Test, TestMultiIncrDecr) {
160
1
  OverrideFlagForSlowTests(
161
1
      "num_operations",
162
1
      strings::Substitute("$0", (FLAGS_num_operations * 100)));
163
1
  OverrideFlagForSlowTests(
164
1
      "num_threads",
165
1
      strings::Substitute("$0", (FLAGS_num_threads * 4)));
166
1
  RunMultiTest(FLAGS_num_operations, FLAGS_num_threads);
167
1
}
168
169
}  // namespace yb