Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/src/share/vm/jfr/periodic/jfrNetworkUtilization.cpp
38920 views
/*1* Copyright (c) 2018, 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 "jfr/jfrEvents.hpp"26#include "jfr/metadata/jfrSerializer.hpp"27#include "jfr/periodic/jfrNetworkUtilization.hpp"28#include "jfr/periodic/jfrOSInterface.hpp"29#include "jfr/utilities/jfrTime.hpp"30#include "jfr/utilities/jfrTypes.hpp"31#include "runtime/os_perf.hpp"32#include "utilities/globalDefinitions.hpp"33#include "utilities/growableArray.hpp"3435struct InterfaceEntry {36char* name;37traceid id;38uint64_t bytes_in;39uint64_t bytes_out;40bool in_use;41};4243static GrowableArray<InterfaceEntry>* _interfaces = NULL;4445void JfrNetworkUtilization::destroy() {46if (_interfaces != NULL) {47for (int i = 0; i < _interfaces->length(); ++i) {48FREE_C_HEAP_ARRAY(char, _interfaces->at(i).name, mtInternal);49}50delete _interfaces;51_interfaces = NULL;52}53}5455static InterfaceEntry& new_entry(const NetworkInterface* iface, GrowableArray<InterfaceEntry>* interfaces) {56assert(iface != NULL, "invariant");57assert(interfaces != NULL, "invariant");5859// single threaded premise60static traceid interface_id = 0;6162const char* name = iface->get_name();63assert(name != NULL, "invariant");6465InterfaceEntry entry;66const size_t length = strlen(name);67entry.name = NEW_C_HEAP_ARRAY(char, length + 1, mtInternal);68strncpy(entry.name, name, length + 1);69entry.id = ++interface_id;70entry.bytes_in = iface->get_bytes_in();71entry.bytes_out = iface->get_bytes_out();72entry.in_use = false;73return _interfaces->at(_interfaces->append(entry));74}7576static GrowableArray<InterfaceEntry>* get_interfaces() {77if (_interfaces == NULL) {78_interfaces = new(ResourceObj::C_HEAP, mtTracing) GrowableArray<InterfaceEntry>(10, true, mtTracing);79}80return _interfaces;81}8283static InterfaceEntry& get_entry(const NetworkInterface* iface) {84// Remember the index we started at last time, since we're most likely looking at them85// in the same order every time.86static int saved_index = -1;8788GrowableArray<InterfaceEntry>* interfaces = get_interfaces();89assert(interfaces != NULL, "invariant");90for (int i = 0; i < _interfaces->length(); ++i) {91saved_index = (saved_index + 1) % _interfaces->length();92if (strcmp(_interfaces->at(saved_index).name, iface->get_name()) == 0) {93return _interfaces->at(saved_index);94}95}96return new_entry(iface, interfaces);97}9899// If current counters are less than previous we assume the interface has been reset100// If no bytes have been either sent or received, we'll also skip the event101static uint64_t rate_per_second(uint64_t current, uint64_t old, const JfrTickspan& interval) {102assert(interval.value() > 0, "invariant");103if (current <= old) {104return 0;105}106return ((current - old) * NANOSECS_PER_SEC) / interval.nanoseconds();107}108109static bool get_interfaces(NetworkInterface** network_interfaces) {110const int ret_val = JfrOSInterface::network_utilization(network_interfaces);111if (ret_val == OS_ERR) {112if (LogJFR) tty->print_cr("Unable to generate network utilization events");113return false;114}115return ret_val != FUNCTIONALITY_NOT_IMPLEMENTED;116}117118class JfrNetworkInterfaceName : public JfrSerializer {119public:120void serialize(JfrCheckpointWriter& writer) {121assert(_interfaces != NULL, "invariant");122const JfrCheckpointContext ctx = writer.context();123const intptr_t count_offset = writer.reserve(sizeof(u4)); // Don't know how many yet124int active_interfaces = 0;125for (int i = 0; i < _interfaces->length(); ++i) {126InterfaceEntry& entry = _interfaces->at(i);127if (entry.in_use) {128entry.in_use = false;129writer.write_key(entry.id);130writer.write(entry.name);131++active_interfaces;132}133}134if (active_interfaces == 0) {135// nothing to write, restore context136writer.set_context(ctx);137return;138}139writer.write_count(active_interfaces, count_offset);140}141};142143static bool register_network_interface_name_serializer() {144assert(_interfaces != NULL, "invariant");145return JfrSerializer::register_serializer(TYPE_NETWORKINTERFACENAME,146false, // require safepoint147false, // disallow caching; we want a callback every rotation148new JfrNetworkInterfaceName());149}150151void JfrNetworkUtilization::send_events() {152ResourceMark rm;153NetworkInterface* network_interfaces;154if (!get_interfaces(&network_interfaces)) {155return;156}157if (LogJFR && Verbose) tty->print_cr("Reporting network utilization");158static JfrTicks last_sample_instant;159const JfrTicks cur_time = JfrTicks::now();160const JfrTickspan interval = last_sample_instant == 0 ? cur_time - cur_time : cur_time - last_sample_instant;161last_sample_instant = cur_time;162for (NetworkInterface *cur = network_interfaces; cur != NULL; cur = cur->next()) {163InterfaceEntry& entry = get_entry(cur);164if (interval.value() > 0) {165const uint64_t current_bytes_in = cur->get_bytes_in();166const uint64_t current_bytes_out = cur->get_bytes_out();167const uint64_t read_rate = rate_per_second(current_bytes_in, entry.bytes_in, interval);168const uint64_t write_rate = rate_per_second(current_bytes_out, entry.bytes_out, interval);169if (read_rate > 0 || write_rate > 0) {170entry.in_use = true;171EventNetworkUtilization event(UNTIMED);172event.set_starttime(cur_time);173event.set_endtime(cur_time);174event.set_networkInterface(entry.id);175event.set_readRate(8 * read_rate);176event.set_writeRate(8 * write_rate);177event.commit();178}179// update existing entry with new values180entry.bytes_in = current_bytes_in;181entry.bytes_out = current_bytes_out;182}183}184185static bool is_serializer_registered = false;186if (!is_serializer_registered) {187is_serializer_registered = register_network_interface_name_serializer();188}189}190191192