Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/test/hotspot/gtest/jfr/test_adaptiveSampler.cpp
41144 views
1
/*
2
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
3
* Copyright (c) 2020, Datadog, Inc. All rights reserved.
4
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5
*
6
* This code is free software; you can redistribute it and/or modify it
7
* under the terms of the GNU General Public License version 2 only, as
8
* published by the Free Software Foundation.
9
*
10
* This code is distributed in the hope that it will be useful, but WITHOUT
11
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13
* version 2 for more details (a copy is included in the LICENSE file that
14
* accompanied this code).
15
*
16
* You should have received a copy of the GNU General Public License version
17
* 2 along with this work; if not, write to the Free Software Foundation,
18
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19
*
20
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21
* or visit www.oracle.com if you need additional information or have any
22
* questions.
23
*
24
*/
25
26
#include "precompiled.hpp"
27
28
// This test performs mocking of certain JVM functionality. This works by
29
// including the source file under test inside an anonymous namespace (which
30
// prevents linking conflicts) with the mocked symbols redefined.
31
32
// The include list should mirror the one found in the included source file -
33
// with the ones that should pick up the mocks removed. Those should be included
34
// later after the mocks have been defined.
35
36
#include <cmath>
37
38
#include "jfr/utilities/jfrAllocation.hpp"
39
#include "jfr/utilities/jfrRandom.inline.hpp"
40
#include "jfr/utilities/jfrSpinlockHelper.hpp"
41
#include "jfr/utilities/jfrTime.hpp"
42
#include "jfr/utilities/jfrTimeConverter.hpp"
43
#include "jfr/utilities/jfrTryLock.hpp"
44
#include "logging/log.hpp"
45
#include "runtime/atomic.hpp"
46
#include "utilities/globalDefinitions.hpp"
47
48
#include "unittest.hpp"
49
50
// #undef SHARE_JFR_SUPPORT_JFRADAPTIVESAMPLER_HPP
51
52
namespace {
53
class MockJfrTimeConverter : public ::JfrTimeConverter {
54
public:
55
static double nano_to_counter_multiplier(bool is_os_time = false) {
56
return 1.0;
57
}
58
static jlong counter_to_nanos(jlong c, bool is_os_time = false) {
59
return c;
60
}
61
static jlong counter_to_millis(jlong c, bool is_os_time = false) {
62
return c * NANOS_PER_MILLISEC;
63
}
64
static jlong nanos_to_countertime(jlong c, bool as_os_time = false) {
65
return c;
66
}
67
};
68
69
class MockJfrTickValue {
70
private:
71
jlong _ticks;
72
public:
73
MockJfrTickValue(jlong ticks) : _ticks(ticks) {};
74
jlong value() {
75
return _ticks;
76
}
77
};
78
class MockJfrTicks {
79
public:
80
static jlong tick;
81
static MockJfrTickValue now() {
82
return MockJfrTickValue(tick);
83
}
84
};
85
86
jlong MockJfrTicks::tick = 0;
87
88
// Reincluding source files in the anonymous namespace unfortunately seems to
89
// behave strangely with precompiled headers (only when using gcc though)
90
#ifndef DONT_USE_PRECOMPILED_HEADER
91
#define DONT_USE_PRECOMPILED_HEADER
92
#endif
93
94
#define JfrTicks MockJfrTicks
95
#define JfrTimeConverter MockJfrTimeConverter
96
97
#include "jfr/support/jfrAdaptiveSampler.hpp"
98
#include "jfr/support/jfrAdaptiveSampler.cpp"
99
100
#undef JfrTimeConverter
101
#undef JfrTicks
102
} // anonymous namespace
103
104
class JfrGTestAdaptiveSampling : public ::testing::Test {
105
protected:
106
const int max_population_per_window = 2000;
107
const int min_population_per_window = 2;
108
const int window_count = 10000;
109
const clock_t window_duration_ms = 100;
110
const size_t expected_sample_points_per_window = 50;
111
const size_t expected_sample_points = expected_sample_points_per_window * (size_t)window_count;
112
const size_t window_lookback_count = 50; // 50 windows == 5 seconds (for a window duration of 100 ms)
113
const double max_sample_bias = 0.11;
114
115
void SetUp() {
116
// Ensure that tests are separated in time by spreading them by 24hrs apart
117
MockJfrTicks::tick += (24 * 60 * 60) * NANOSECS_PER_SEC;
118
}
119
120
void TearDown() {
121
// nothing
122
}
123
124
void assertDistributionProperties(int distr_slots, jlong* population, jlong* sample, size_t population_size, size_t sample_size, const char* msg) {
125
size_t population_sum = 0;
126
size_t sample_sum = 0;
127
for (int i = 0; i < distr_slots; i++) {
128
population_sum += i * population[i];
129
sample_sum += i * sample[i];
130
}
131
132
double population_mean = population_sum / (double)population_size;
133
double sample_mean = sample_sum / (double)sample_size;
134
135
double population_variance = 0;
136
double sample_variance = 0;
137
for (int i = 0; i < distr_slots; i++) {
138
double population_diff = i - population_mean;
139
population_variance = population[i] * population_diff * population_diff;
140
141
double sample_diff = i - sample_mean;
142
sample_variance = sample[i] * sample_diff * sample_diff;
143
}
144
population_variance = population_variance / (population_size - 1);
145
sample_variance = sample_variance / (sample_size - 1);
146
double population_stdev = sqrt(population_variance);
147
double sample_stdev = sqrt(sample_variance);
148
149
// make sure the standard deviation is ok
150
EXPECT_NEAR(population_stdev, sample_stdev, 0.5) << msg;
151
// make sure that the subsampled set mean is within 2-sigma of the original set mean
152
EXPECT_NEAR(population_mean, sample_mean, population_stdev) << msg;
153
// make sure that the original set mean is within 2-sigma of the subsampled set mean
154
EXPECT_NEAR(sample_mean, population_mean, sample_stdev) << msg;
155
}
156
157
typedef size_t(JfrGTestAdaptiveSampling::* incoming)() const;
158
void test(incoming inc, size_t events_per_window, double expectation, const char* description);
159
160
public:
161
size_t incoming_uniform() const {
162
return os::random() % max_population_per_window + min_population_per_window;
163
}
164
165
size_t incoming_bursty_10_percent() const {
166
bool is_burst = (os::random() % 100) < 10; // 10% burst chance
167
return is_burst ? max_population_per_window : min_population_per_window;
168
}
169
170
size_t incoming_bursty_90_percent() const {
171
bool is_burst = (os::random() % 100) < 90; // 90% burst chance
172
return is_burst ? max_population_per_window : min_population_per_window;
173
}
174
175
size_t incoming_low_rate() const {
176
return min_population_per_window;
177
}
178
179
size_t incoming_high_rate() const {
180
return max_population_per_window;
181
}
182
183
size_t incoming_burst_eval(size_t& count, size_t mod_value) const {
184
return count++ % 10 == mod_value ? max_population_per_window : 0;
185
}
186
187
size_t incoming_early_burst() const {
188
static size_t count = 1;
189
return incoming_burst_eval(count, 1);
190
}
191
192
size_t incoming_mid_burst() const {
193
static size_t count = 1;
194
return incoming_burst_eval(count, 5);
195
}
196
197
size_t incoming_late_burst() const {
198
static size_t count = 1;
199
return incoming_burst_eval(count, 0);
200
}
201
};
202
203
void JfrGTestAdaptiveSampling::test(JfrGTestAdaptiveSampling::incoming inc, size_t sample_points_per_window, double error_factor, const char* const description) {
204
assert(description != NULL, "invariant");
205
char output[1024] = "Adaptive sampling: ";
206
strcat(output, description);
207
fprintf(stdout, "=== %s\n", output);
208
jlong population[100] = { 0 };
209
jlong sample[100] = { 0 };
210
::JfrGTestFixedRateSampler sampler = ::JfrGTestFixedRateSampler(expected_sample_points_per_window, window_duration_ms, window_lookback_count);
211
EXPECT_TRUE(sampler.initialize());
212
213
size_t population_size = 0;
214
size_t sample_size = 0;
215
for (int t = 0; t < window_count; t++) {
216
const size_t incoming_events = (this->*inc)();
217
for (size_t i = 0; i < incoming_events; i++) {
218
++population_size;
219
size_t index = os::random() % 100;
220
population[index] += 1;
221
if (sampler.sample()) {
222
++sample_size;
223
sample[index] += 1;
224
}
225
}
226
MockJfrTicks::tick += window_duration_ms * NANOSECS_PER_MILLISEC + 1;
227
sampler.sample(); // window rotation
228
}
229
230
const size_t target_sample_size = sample_points_per_window * window_count;
231
EXPECT_NEAR(target_sample_size, sample_size, expected_sample_points * error_factor) << output;
232
strcat(output, ", hit distribution");
233
assertDistributionProperties(100, population, sample, population_size, sample_size, output);
234
}
235
236
TEST_VM_F(JfrGTestAdaptiveSampling, DISABLED_uniform_rate) {
237
test(&JfrGTestAdaptiveSampling::incoming_uniform, expected_sample_points_per_window, 0.05, "random uniform, all samples");
238
}
239
240
TEST_VM_F(JfrGTestAdaptiveSampling, DISABLED_low_rate) {
241
test(&JfrGTestAdaptiveSampling::incoming_low_rate, min_population_per_window, 0.05, "low rate");
242
}
243
244
TEST_VM_F(JfrGTestAdaptiveSampling, DISABLED_high_rate) {
245
test(&JfrGTestAdaptiveSampling::incoming_high_rate, expected_sample_points_per_window, 0.02, "high rate");
246
}
247
248
// We can think of the windows as splitting up a time period, for example a second (window_duration_ms = 100)
249
// The burst tests for early, mid and late apply a burst rate at a selected window, with other windows having no incoming input.
250
//
251
// - early during the first window of a new time period
252
// - mid during the middle window of a new time period
253
// - late during the last window of a new time period
254
//
255
// The tests verify the total sample size correspond to the selected bursts:
256
//
257
// - early start of a second -> each second will have sampled the window set point for a single window only since no debt has accumulated into the new time period.
258
// - mid middle of the second -> each second will have sampled the window set point + accumulated debt for the first 4 windows.
259
// - late end of the second -> each second will have sampled the window set point + accumulated debt for the first 9 windows (i.e. it will have sampled all)
260
//
261
262
TEST_VM_F(JfrGTestAdaptiveSampling, DISABLED_early_burst) {
263
test(&JfrGTestAdaptiveSampling::incoming_early_burst, expected_sample_points_per_window, 0.9, "early burst");
264
}
265
266
TEST_VM_F(JfrGTestAdaptiveSampling, DISABLED_mid_burst) {
267
test(&JfrGTestAdaptiveSampling::incoming_mid_burst, expected_sample_points_per_window, 0.5, "mid burst");
268
}
269
270
TEST_VM_F(JfrGTestAdaptiveSampling, DISABLED_late_burst) {
271
test(&JfrGTestAdaptiveSampling::incoming_late_burst, expected_sample_points_per_window, 0.0, "late burst");
272
}
273
274
// These are randomized burst tests
275
TEST_VM_F(JfrGTestAdaptiveSampling, DISABLED_bursty_rate_10_percent) {
276
test(&JfrGTestAdaptiveSampling::incoming_bursty_10_percent, expected_sample_points_per_window, 0.96, "bursty 10%");
277
}
278
279
TEST_VM_F(JfrGTestAdaptiveSampling, DISABLED_bursty_rate_90_percent) {
280
test(&JfrGTestAdaptiveSampling::incoming_bursty_10_percent, expected_sample_points_per_window, 0.96, "bursty 90%");
281
}
282
283