Skip to content

Commit 313758a

Browse files
mar-kolyaJaroslav Bachorik
authored and
Jaroslav Bachorik
committedApr 29, 2020
8243489: Thread CPU Load event may contain wrong data for CPU time under certain conditions
Reviewed-by: jbachorik
1 parent 5bbee05 commit 313758a

File tree

2 files changed

+82
-3
lines changed

2 files changed

+82
-3
lines changed
 

‎src/hotspot/share/jfr/periodic/jfrThreadCPULoadEvent.cpp

+2-3
Original file line numberDiff line numberDiff line change
@@ -87,15 +87,14 @@ bool JfrThreadCPULoadEvent::update_event(EventThreadCPULoad& event, JavaThread*
8787
// Avoid reporting percentages above the theoretical max
8888
if (user_time + system_time > wallclock_time) {
8989
jlong excess = user_time + system_time - wallclock_time;
90+
cur_cpu_time -= excess;
9091
if (user_time > excess) {
9192
user_time -= excess;
9293
cur_user_time -= excess;
93-
cur_cpu_time -= excess;
9494
} else {
95-
cur_cpu_time -= excess;
9695
excess -= user_time;
96+
cur_user_time -= user_time;
9797
user_time = 0;
98-
cur_user_time = 0;
9998
system_time -= excess;
10099
}
101100
}

‎test/hotspot/gtest/jfr/test_threadCpuLoad.cpp

+80
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,12 @@ TEST_VM_F(JfrTestThreadCPULoadSingle, SingleCpu) {
148148
EXPECT_TRUE(JfrThreadCPULoadEvent::update_event(event, thread, 400 * NANOSECS_PER_MILLISEC, 1));
149149
EXPECT_FLOAT_EQ(0.25, event.user);
150150
EXPECT_FLOAT_EQ(0.25, event.system);
151+
152+
MockOs::user_cpu_time += 50 * NANOSECS_PER_MILLISEC;
153+
MockOs::system_cpu_time += 50 * NANOSECS_PER_MILLISEC;
154+
EXPECT_TRUE(JfrThreadCPULoadEvent::update_event(event, thread, (400 + 400) * NANOSECS_PER_MILLISEC, 1));
155+
EXPECT_FLOAT_EQ(0.125, event.user);
156+
EXPECT_FLOAT_EQ(0.125, event.system);
151157
}
152158

153159
TEST_VM_F(JfrTestThreadCPULoadSingle, MultipleCpus) {
@@ -177,6 +183,43 @@ TEST_VM_F(JfrTestThreadCPULoadSingle, UserAboveMaximum) {
177183
EXPECT_TRUE(JfrThreadCPULoadEvent::update_event(event, thread, (200 + 400) * NANOSECS_PER_MILLISEC, 1));
178184
EXPECT_FLOAT_EQ(0.25, event.user);
179185
EXPECT_FLOAT_EQ(0, event.system);
186+
187+
// Third call: make sure there are no leftovers
188+
MockOs::user_cpu_time += 50 * NANOSECS_PER_MILLISEC;
189+
MockOs::system_cpu_time += 50 * NANOSECS_PER_MILLISEC;
190+
EXPECT_TRUE(JfrThreadCPULoadEvent::update_event(event, thread, (200 + 400 + 400) * NANOSECS_PER_MILLISEC, 1));
191+
EXPECT_FLOAT_EQ(0.125, event.user);
192+
EXPECT_FLOAT_EQ(0.125, event.system);
193+
}
194+
195+
TEST_VM_F(JfrTestThreadCPULoadSingle, UserAboveMaximumNonZeroBase) {
196+
197+
// Setup a non zero base
198+
// Previously there was a bug when cur_user_time would be reset to zero and test that uses zero base would fail to detect it
199+
MockOs::user_cpu_time = 100 * NANOSECS_PER_MILLISEC;
200+
MockOs::system_cpu_time = 100 * NANOSECS_PER_MILLISEC;
201+
EXPECT_TRUE(JfrThreadCPULoadEvent::update_event(event, thread, 400 * NANOSECS_PER_MILLISEC, 1));
202+
EXPECT_FLOAT_EQ(0.25, event.user);
203+
EXPECT_FLOAT_EQ(0.25, event.system);
204+
205+
// First call will not report above 100%
206+
MockOs::user_cpu_time += 200 * NANOSECS_PER_MILLISEC;
207+
MockOs::system_cpu_time += 100 * NANOSECS_PER_MILLISEC;
208+
EXPECT_TRUE(JfrThreadCPULoadEvent::update_event(event, thread, (400 + 200) * NANOSECS_PER_MILLISEC, 1));
209+
EXPECT_FLOAT_EQ(0.5, event.user);
210+
EXPECT_FLOAT_EQ(0.5, event.system);
211+
212+
// Second call will see an extra 100 millisecs user time from the remainder
213+
EXPECT_TRUE(JfrThreadCPULoadEvent::update_event(event, thread, (400 + 200 + 400) * NANOSECS_PER_MILLISEC, 1));
214+
EXPECT_FLOAT_EQ(0.25, event.user);
215+
EXPECT_FLOAT_EQ(0, event.system);
216+
217+
// Third call: make sure there are no leftovers
218+
MockOs::user_cpu_time += 50 * NANOSECS_PER_MILLISEC;
219+
MockOs::system_cpu_time += 50 * NANOSECS_PER_MILLISEC;
220+
EXPECT_TRUE(JfrThreadCPULoadEvent::update_event(event, thread, (400 + 200 + 400 + 400) * NANOSECS_PER_MILLISEC, 1));
221+
EXPECT_FLOAT_EQ(0.125, event.user);
222+
EXPECT_FLOAT_EQ(0.125, event.system);
180223
}
181224

182225
TEST_VM_F(JfrTestThreadCPULoadSingle, SystemAboveMaximum) {
@@ -192,6 +235,43 @@ TEST_VM_F(JfrTestThreadCPULoadSingle, SystemAboveMaximum) {
192235
EXPECT_TRUE(JfrThreadCPULoadEvent::update_event(event, thread, (200 + 400) * NANOSECS_PER_MILLISEC, 1));
193236
EXPECT_FLOAT_EQ(0.25, event.user);
194237
EXPECT_FLOAT_EQ(0.25, event.system);
238+
239+
// Third call: make sure there are no leftovers
240+
MockOs::user_cpu_time += 50 * NANOSECS_PER_MILLISEC;
241+
MockOs::system_cpu_time += 50 * NANOSECS_PER_MILLISEC;
242+
EXPECT_TRUE(JfrThreadCPULoadEvent::update_event(event, thread, (200 + 400 + 400) * NANOSECS_PER_MILLISEC, 1));
243+
EXPECT_FLOAT_EQ(0.125, event.user);
244+
EXPECT_FLOAT_EQ(0.125, event.system);
245+
}
246+
247+
TEST_VM_F(JfrTestThreadCPULoadSingle, SystemAboveMaximumNonZeroBase) {
248+
249+
// Setup a non zero base
250+
// Previously there was a bug when cur_user_time would be reset to zero and test that uses zero base would fail to detect it
251+
MockOs::user_cpu_time = 100 * NANOSECS_PER_MILLISEC;
252+
MockOs::system_cpu_time = 100 * NANOSECS_PER_MILLISEC;
253+
EXPECT_TRUE(JfrThreadCPULoadEvent::update_event(event, thread, 400 * NANOSECS_PER_MILLISEC, 1));
254+
EXPECT_FLOAT_EQ(0.25, event.user);
255+
EXPECT_FLOAT_EQ(0.25, event.system);
256+
257+
// First call will not report above 100%
258+
MockOs::user_cpu_time += 100 * NANOSECS_PER_MILLISEC;
259+
MockOs::system_cpu_time += 300 * NANOSECS_PER_MILLISEC;
260+
EXPECT_TRUE(JfrThreadCPULoadEvent::update_event(event, thread, (400 + 200) * NANOSECS_PER_MILLISEC, 1));
261+
EXPECT_FLOAT_EQ(0, event.user);
262+
EXPECT_FLOAT_EQ(1, event.system);
263+
264+
// Second call will see an extra 100 millisecs user and system time from the remainder
265+
EXPECT_TRUE(JfrThreadCPULoadEvent::update_event(event, thread, (400 + 200 + 400) * NANOSECS_PER_MILLISEC, 1));
266+
EXPECT_FLOAT_EQ(0.25, event.user);
267+
EXPECT_FLOAT_EQ(0.25, event.system);
268+
269+
// Third call: make sure there are no leftovers
270+
MockOs::user_cpu_time += 50 * NANOSECS_PER_MILLISEC;
271+
MockOs::system_cpu_time += 50 * NANOSECS_PER_MILLISEC;
272+
EXPECT_TRUE(JfrThreadCPULoadEvent::update_event(event, thread, (400 + 200 + 400 + 400) * NANOSECS_PER_MILLISEC, 1));
273+
EXPECT_FLOAT_EQ(0.125, event.user);
274+
EXPECT_FLOAT_EQ(0.125, event.system);
195275
}
196276

197277
TEST_VM_F(JfrTestThreadCPULoadSingle, SystemTimeDecreasing) {

0 commit comments

Comments
 (0)
Please sign in to comment.