YugabyteDB (2.13.1.0-b60, 21121d69985fbf76aa6958d8f04a9bfa936293b5)

Coverage Report

Created: 2022-03-22 16:43

/Users/deen/code/yugabyte-db/src/yb/util/debug/trace_event_synthetic_delay.cc
Line
Count
Source (jump to first uncovered line)
1
// Copyright 2014 The Chromium Authors. All rights reserved.
2
// Use of this source code is governed by a BSD-style license that can be
3
// found in the LICENSE file.
4
//
5
// The following only applies to changes made to this file as part of YugaByte development.
6
//
7
// Portions Copyright (c) YugaByte, Inc.
8
//
9
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
10
// in compliance with the License.  You may obtain a copy of the License at
11
//
12
// http://www.apache.org/licenses/LICENSE-2.0
13
//
14
// Unless required by applicable law or agreed to in writing, software distributed under the License
15
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
16
// or implied.  See the License for the specific language governing permissions and limitations
17
// under the License.
18
//
19
20
#include "yb/util/debug/trace_event_synthetic_delay.h"
21
22
#include "yb/gutil/singleton.h"
23
24
namespace {
25
const int kMaxSyntheticDelays = 32;
26
}  // namespace
27
28
namespace yb {
29
namespace debug {
30
31
35
TraceEventSyntheticDelayClock::TraceEventSyntheticDelayClock() {}
32
10
TraceEventSyntheticDelayClock::~TraceEventSyntheticDelayClock() {}
33
34
class TraceEventSyntheticDelayRegistry : public TraceEventSyntheticDelayClock {
35
 public:
36
  static TraceEventSyntheticDelayRegistry* GetInstance();
37
38
  TraceEventSyntheticDelay* GetOrCreateDelay(const char* name);
39
  void ResetAllDelays();
40
41
  // TraceEventSyntheticDelayClock implementation.
42
  MonoTime Now() override;
43
44
 private:
45
  TraceEventSyntheticDelayRegistry();
46
47
  friend class Singleton<TraceEventSyntheticDelayRegistry>;
48
49
  Mutex lock_;
50
  TraceEventSyntheticDelay delays_[kMaxSyntheticDelays];
51
  TraceEventSyntheticDelay dummy_delay_;
52
  base::subtle::Atomic32 delay_count_;
53
54
  DISALLOW_COPY_AND_ASSIGN(TraceEventSyntheticDelayRegistry);
55
};
56
57
TraceEventSyntheticDelay::TraceEventSyntheticDelay()
58
825
    : mode_(STATIC), begin_count_(0), trigger_count_(0), clock_(nullptr) {}
59
60
0
TraceEventSyntheticDelay::~TraceEventSyntheticDelay() {}
61
62
TraceEventSyntheticDelay* TraceEventSyntheticDelay::Lookup(
63
10
    const std::string& name) {
64
10
  return TraceEventSyntheticDelayRegistry::GetInstance()->GetOrCreateDelay(
65
10
      name.c_str());
66
10
}
67
68
void TraceEventSyntheticDelay::Initialize(
69
    const std::string& name,
70
10
    TraceEventSyntheticDelayClock* clock) {
71
10
  name_ = name;
72
10
  clock_ = clock;
73
10
}
74
75
22
void TraceEventSyntheticDelay::SetTargetDuration(const MonoDelta& target_duration) {
76
22
  MutexLock lock(lock_);
77
22
  target_duration_ = target_duration;
78
22
  trigger_count_ = 0;
79
22
  begin_count_ = 0;
80
22
}
81
82
3
void TraceEventSyntheticDelay::SetMode(Mode mode) {
83
3
  MutexLock lock(lock_);
84
3
  mode_ = mode;
85
3
}
86
87
21
void TraceEventSyntheticDelay::SetClock(TraceEventSyntheticDelayClock* clock) {
88
21
  MutexLock lock(lock_);
89
21
  clock_ = clock;
90
21
}
91
92
6
void TraceEventSyntheticDelay::Begin() {
93
  // Note that we check for a non-zero target duration without locking to keep
94
  // things quick for the common case when delays are disabled. Since the delay
95
  // calculation is done with a lock held, it will always be correct. The only
96
  // downside of this is that we may fail to apply some delays when the target
97
  // duration changes.
98
6
  ANNOTATE_BENIGN_RACE(&target_duration_, "Synthetic delay duration");
99
6
  if (!target_duration_.Initialized())
100
0
    return;
101
102
6
  MonoTime start_time = clock_->Now();
103
6
  {
104
6
    MutexLock lock(lock_);
105
6
    if (++begin_count_ != 1)
106
1
      return;
107
5
    end_time_ = CalculateEndTimeLocked(start_time);
108
5
  }
109
5
}
110
111
11
void TraceEventSyntheticDelay::BeginParallel(MonoTime* out_end_time) {
112
  // See note in Begin().
113
11
  ANNOTATE_BENIGN_RACE(&target_duration_, "Synthetic delay duration");
114
11
  if (!target_duration_.Initialized()) {
115
1
    *out_end_time = MonoTime();
116
1
    return;
117
1
  }
118
119
10
  MonoTime start_time = clock_->Now();
120
10
  {
121
10
    MutexLock lock(lock_);
122
10
    *out_end_time = CalculateEndTimeLocked(start_time);
123
10
  }
124
10
}
125
126
8
void TraceEventSyntheticDelay::End() {
127
  // See note in Begin().
128
8
  ANNOTATE_BENIGN_RACE(&target_duration_, "Synthetic delay duration");
129
8
  if (!target_duration_.Initialized())
130
0
    return;
131
132
8
  MonoTime end_time;
133
8
  {
134
8
    MutexLock lock(lock_);
135
8
    if (!begin_count_ || 
--begin_count_ != 06
)
136
3
      return;
137
5
    end_time = end_time_;
138
5
  }
139
5
  if (end_time.Initialized())
140
5
    ApplyDelay(end_time);
141
5
}
142
143
11
void TraceEventSyntheticDelay::EndParallel(const MonoTime& end_time) {
144
11
  if (end_time.Initialized())
145
7
    ApplyDelay(end_time);
146
11
}
147
148
MonoTime TraceEventSyntheticDelay::CalculateEndTimeLocked(
149
15
    const MonoTime& start_time) {
150
15
  if (mode_ == ONE_SHOT && 
trigger_count_++3
)
151
1
    return MonoTime();
152
14
  else if (mode_ == ALTERNATING && 
trigger_count_++ % 24
)
153
2
    return MonoTime();
154
12
  MonoTime end = start_time;
155
12
  end.AddDelta(target_duration_);
156
12
  return end;
157
15
}
158
159
12
void TraceEventSyntheticDelay::ApplyDelay(const MonoTime& end_time) {
160
12
  TRACE_EVENT0("synthetic_delay", name_.c_str());
161
988
  while (clock_->Now().ComesBefore(end_time)) {
162
    // Busy loop.
163
976
  }
164
12
}
165
166
TraceEventSyntheticDelayRegistry*
167
52
TraceEventSyntheticDelayRegistry::GetInstance() {
168
52
  return Singleton<TraceEventSyntheticDelayRegistry>::get();
169
52
}
170
171
TraceEventSyntheticDelayRegistry::TraceEventSyntheticDelayRegistry()
172
25
    : delay_count_(0) {}
173
174
TraceEventSyntheticDelay* TraceEventSyntheticDelayRegistry::GetOrCreateDelay(
175
23
    const char* name) {
176
  // Try to find an existing delay first without locking to make the common case
177
  // fast.
178
23
  int delay_count = base::subtle::Acquire_Load(&delay_count_);
179
23
  for (int i = 0; i < delay_count; 
++i0
) {
180
13
    if (!strcmp(name, delays_[i].name_.c_str()))
181
13
      return &delays_[i];
182
13
  }
183
184
10
  MutexLock lock(lock_);
185
10
  delay_count = base::subtle::Acquire_Load(&delay_count_);
186
10
  for (int i = 0; i < delay_count; 
++i0
) {
187
0
    if (!strcmp(name, delays_[i].name_.c_str()))
188
0
      return &delays_[i];
189
0
  }
190
191
10
  DCHECK(delay_count < kMaxSyntheticDelays)
192
0
      << "must increase kMaxSyntheticDelays";
193
10
  if (delay_count >= kMaxSyntheticDelays)
194
0
    return &dummy_delay_;
195
196
10
  delays_[delay_count].Initialize(std::string(name), this);
197
10
  base::subtle::Release_Store(&delay_count_, delay_count + 1);
198
10
  return &delays_[delay_count];
199
10
}
200
201
0
MonoTime TraceEventSyntheticDelayRegistry::Now() {
202
0
  return MonoTime::Now();
203
0
}
204
205
29
void TraceEventSyntheticDelayRegistry::ResetAllDelays() {
206
29
  MutexLock lock(lock_);
207
29
  int delay_count = base::subtle::Acquire_Load(&delay_count_);
208
40
  for (int i = 0; i < delay_count; 
++i11
) {
209
11
    delays_[i].SetTargetDuration(MonoDelta());
210
11
    delays_[i].SetClock(this);
211
11
  }
212
29
}
213
214
29
void ResetTraceEventSyntheticDelays() {
215
29
  TraceEventSyntheticDelayRegistry::GetInstance()->ResetAllDelays();
216
29
}
217
218
}  // namespace debug
219
}  // namespace yb
220
221
namespace trace_event_internal {
222
223
ScopedSyntheticDelay::ScopedSyntheticDelay(const char* name,
224
                                           AtomicWord* impl_ptr)
225
9
    : delay_impl_(GetOrCreateDelay(name, impl_ptr)) {
226
9
  delay_impl_->BeginParallel(&end_time_);
227
9
}
228
229
9
ScopedSyntheticDelay::~ScopedSyntheticDelay() {
230
9
  delay_impl_->EndParallel(end_time_);
231
9
}
232
233
yb::debug::TraceEventSyntheticDelay* GetOrCreateDelay(
234
    const char* name,
235
23
    AtomicWord* impl_ptr) {
236
23
  yb::debug::TraceEventSyntheticDelay* delay_impl =
237
23
      reinterpret_cast<yb::debug::TraceEventSyntheticDelay*>(
238
23
          base::subtle::Acquire_Load(impl_ptr));
239
23
  if (!delay_impl) {
240
13
    delay_impl = yb::debug::TraceEventSyntheticDelayRegistry::GetInstance()
241
13
                     ->GetOrCreateDelay(name);
242
13
    base::subtle::Release_Store(
243
13
        impl_ptr, reinterpret_cast<AtomicWord>(delay_impl));
244
13
  }
245
23
  return delay_impl;
246
23
}
247
248
}  // namespace trace_event_internal