Path: blob/master/src/hotspot/share/jfr/periodic/jfrThreadCPULoadEvent.cpp
41149 views
/*1* Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#include "precompiled.hpp"25#include "logging/log.hpp"26#include "jfr/jfrEvents.hpp"27#include "jfr/periodic/jfrThreadCPULoadEvent.hpp"28#include "jfr/support/jfrThreadId.hpp"29#include "jfr/support/jfrThreadLocal.hpp"30#include "jfr/utilities/jfrThreadIterator.hpp"31#include "jfr/utilities/jfrTime.hpp"32#include "utilities/globalDefinitions.hpp"33#include "runtime/os.hpp"3435jlong JfrThreadCPULoadEvent::get_wallclock_time() {36return os::javaTimeNanos();37}3839int JfrThreadCPULoadEvent::_last_active_processor_count = 0;4041int JfrThreadCPULoadEvent::get_processor_count() {42int cur_processor_count = os::active_processor_count();43int last_processor_count = _last_active_processor_count;44_last_active_processor_count = cur_processor_count;4546// If the number of processors decreases, we don't know at what point during47// the sample interval this happened, so use the largest number to try48// to avoid percentages above 100%49return MAX2(cur_processor_count, last_processor_count);50}5152// Returns false if the thread has not been scheduled since the last call to updateEvent53// (i.e. the delta for both system and user time is 0 milliseconds)54bool JfrThreadCPULoadEvent::update_event(EventThreadCPULoad& event, JavaThread* thread, jlong cur_wallclock_time, int processor_count) {55JfrThreadLocal* const tl = thread->jfr_thread_local();5657jlong cur_cpu_time = os::thread_cpu_time(thread, true);58jlong prev_cpu_time = tl->get_cpu_time();5960jlong prev_wallclock_time = tl->get_wallclock_time();61tl->set_wallclock_time(cur_wallclock_time);6263// Threshold of 1 ms64if (cur_cpu_time - prev_cpu_time < 1 * NANOSECS_PER_MILLISEC) {65return false;66}6768jlong cur_user_time = os::thread_cpu_time(thread, false);69jlong prev_user_time = tl->get_user_time();7071jlong cur_system_time = cur_cpu_time - cur_user_time;72jlong prev_system_time = prev_cpu_time - prev_user_time;7374// The user and total cpu usage clocks can have different resolutions, which can75// make us see decreasing system time. Ensure time doesn't go backwards.76if (prev_system_time > cur_system_time) {77cur_cpu_time += prev_system_time - cur_system_time;78cur_system_time = prev_system_time;79}8081jlong user_time = cur_user_time - prev_user_time;82jlong system_time = cur_system_time - prev_system_time;83jlong wallclock_time = cur_wallclock_time - prev_wallclock_time;84jlong total_available_time = wallclock_time * processor_count;8586// Avoid reporting percentages above the theoretical max87if (user_time + system_time > wallclock_time) {88jlong excess = user_time + system_time - wallclock_time;89cur_cpu_time -= excess;90if (user_time > excess) {91user_time -= excess;92cur_user_time -= excess;93} else {94excess -= user_time;95cur_user_time -= user_time;96user_time = 0;97system_time -= excess;98}99}100event.set_user(total_available_time > 0 ? (double)user_time / total_available_time : 0);101event.set_system(total_available_time > 0 ? (double)system_time / total_available_time : 0);102tl->set_user_time(cur_user_time);103tl->set_cpu_time(cur_cpu_time);104return true;105}106107void JfrThreadCPULoadEvent::send_events() {108Thread* periodic_thread = Thread::current();109JfrThreadLocal* const periodic_thread_tl = periodic_thread->jfr_thread_local();110traceid periodic_thread_id = periodic_thread_tl->thread_id();111const int processor_count = JfrThreadCPULoadEvent::get_processor_count();112JfrTicks event_time = JfrTicks::now();113jlong cur_wallclock_time = JfrThreadCPULoadEvent::get_wallclock_time();114115JfrJavaThreadIterator iter;116int number_of_threads = 0;117while (iter.has_next()) {118JavaThread* const jt = iter.next();119assert(jt != NULL, "invariant");120++number_of_threads;121EventThreadCPULoad event(UNTIMED);122if (JfrThreadCPULoadEvent::update_event(event, jt, cur_wallclock_time, processor_count)) {123event.set_starttime(event_time);124if (jt != periodic_thread) {125// Commit reads the thread id from this thread's trace data, so put it there temporarily126periodic_thread_tl->set_thread_id(JFR_THREAD_ID(jt));127} else {128periodic_thread_tl->set_thread_id(periodic_thread_id);129}130event.commit();131}132}133log_trace(jfr)("Measured CPU usage for %d threads in %.3f milliseconds", number_of_threads,134(double)(JfrTicks::now() - event_time).milliseconds());135// Restore this thread's thread id136periodic_thread_tl->set_thread_id(periodic_thread_id);137}138139void JfrThreadCPULoadEvent::send_event_for_thread(JavaThread* jt) {140EventThreadCPULoad event;141if (event.should_commit()) {142if (update_event(event, jt, get_wallclock_time(), get_processor_count())) {143event.commit();144}145}146}147148149