src/share/vm/jfr/periodic/jfrNetworkUtilization.cpp

Thu, 13 Dec 2018 14:21:04 +0100

author
egahlin
date
Thu, 13 Dec 2018 14:21:04 +0100
changeset 9874
9c3c8469d9be
parent 9858
b985cbb00e68
permissions
-rw-r--r--

8215175: Inconsistencies in JFR event metadata
Reviewed-by: mgronlun

     1 /*
     2  * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.
     8  *
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    12  * version 2 for more details (a copy is included in the LICENSE file that
    13  * accompanied this code).
    14  *
    15  * You should have received a copy of the GNU General Public License version
    16  * 2 along with this work; if not, write to the Free Software Foundation,
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    18  *
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    20  * or visit www.oracle.com if you need additional information or have any
    21  * questions.
    22  *
    23  */
    25 #include "precompiled.hpp"
    26 #include "jfr/jfrEvents.hpp"
    27 #include "jfr/metadata/jfrSerializer.hpp"
    28 #include "jfr/periodic/jfrNetworkUtilization.hpp"
    29 #include "jfr/periodic/jfrOSInterface.hpp"
    30 #include "jfr/utilities/jfrTime.hpp"
    31 #include "jfr/utilities/jfrTypes.hpp"
    32 #include "runtime/os_perf.hpp"
    33 #include "utilities/globalDefinitions.hpp"
    34 #include "utilities/growableArray.hpp"
    36 struct InterfaceEntry {
    37   char* name;
    38   traceid id;
    39   uint64_t bytes_in;
    40   uint64_t bytes_out;
    41   bool in_use;
    42 };
    44 static GrowableArray<InterfaceEntry>* _interfaces = NULL;
    46 void JfrNetworkUtilization::destroy() {
    47   if (_interfaces != NULL) {
    48     for (int i = 0; i < _interfaces->length(); ++i) {
    49       FREE_C_HEAP_ARRAY(char, _interfaces->at(i).name, mtInternal);
    50     }
    51     delete _interfaces;
    52     _interfaces = NULL;
    53   }
    54 }
    56 static InterfaceEntry& new_entry(const NetworkInterface* iface, GrowableArray<InterfaceEntry>* interfaces) {
    57   assert(iface != NULL, "invariant");
    58   assert(interfaces != NULL, "invariant");
    60   // single threaded premise
    61   static traceid interface_id = 0;
    63   const char* name = iface->get_name();
    64   assert(name != NULL, "invariant");
    66   InterfaceEntry entry;
    67   const size_t length = strlen(name);
    68   entry.name = NEW_C_HEAP_ARRAY(char, length + 1, mtInternal);
    69   strncpy(entry.name, name, length + 1);
    70   entry.id = ++interface_id;
    71   entry.bytes_in = iface->get_bytes_in();
    72   entry.bytes_out = iface->get_bytes_out();
    73   entry.in_use = false;
    74   return _interfaces->at(_interfaces->append(entry));
    75 }
    77 static GrowableArray<InterfaceEntry>* get_interfaces() {
    78   if (_interfaces == NULL) {
    79     _interfaces = new(ResourceObj::C_HEAP, mtTracing) GrowableArray<InterfaceEntry>(10, true, mtTracing);
    80   }
    81   return _interfaces;
    82 }
    84 static InterfaceEntry& get_entry(const NetworkInterface* iface) {
    85   // Remember the index we started at last time, since we're most likely looking at them
    86   // in the same order every time.
    87   static int saved_index = -1;
    89   GrowableArray<InterfaceEntry>* interfaces = get_interfaces();
    90   assert(interfaces != NULL, "invariant");
    91   for (int i = 0; i < _interfaces->length(); ++i) {
    92     saved_index = (saved_index + 1) % _interfaces->length();
    93     if (strcmp(_interfaces->at(saved_index).name, iface->get_name()) == 0) {
    94       return _interfaces->at(saved_index);
    95     }
    96   }
    97   return new_entry(iface, interfaces);
    98 }
   100 // If current counters are less than previous we assume the interface has been reset
   101 // If no bytes have been either sent or received, we'll also skip the event
   102 static uint64_t rate_per_second(uint64_t current, uint64_t old, const JfrTickspan& interval) {
   103   assert(interval.value() > 0, "invariant");
   104   if (current <= old) {
   105     return 0;
   106   }
   107   return ((current - old) * NANOSECS_PER_SEC) / interval.nanoseconds();
   108 }
   110 static bool get_interfaces(NetworkInterface** network_interfaces) {
   111   const int ret_val = JfrOSInterface::network_utilization(network_interfaces);
   112   if (ret_val == OS_ERR) {
   113     if (LogJFR) tty->print_cr("Unable to generate network utilization events");
   114     return false;
   115   }
   116   return ret_val != FUNCTIONALITY_NOT_IMPLEMENTED;
   117 }
   119 class JfrNetworkInterfaceName : public JfrSerializer {
   120  public:
   121   void serialize(JfrCheckpointWriter& writer) {
   122     assert(_interfaces != NULL, "invariant");
   123     const JfrCheckpointContext ctx = writer.context();
   124     const intptr_t count_offset = writer.reserve(sizeof(u4)); // Don't know how many yet
   125     int active_interfaces = 0;
   126     for (int i = 0; i < _interfaces->length(); ++i) {
   127       InterfaceEntry& entry = _interfaces->at(i);
   128       if (entry.in_use) {
   129         entry.in_use = false;
   130         writer.write_key(entry.id);
   131         writer.write(entry.name);
   132         ++active_interfaces;
   133       }
   134     }
   135     if (active_interfaces == 0) {
   136       // nothing to write, restore context
   137       writer.set_context(ctx);
   138       return;
   139     }
   140     writer.write_count(active_interfaces, count_offset);
   141   }
   142 };
   144 static bool register_network_interface_name_serializer() {
   145   assert(_interfaces != NULL, "invariant");
   146   return JfrSerializer::register_serializer(TYPE_NETWORKINTERFACENAME,
   147                                             false, // require safepoint
   148                                             false, // disallow caching; we want a callback every rotation
   149                                             new JfrNetworkInterfaceName());
   150 }
   152 void JfrNetworkUtilization::send_events() {
   153   ResourceMark rm;
   154   NetworkInterface* network_interfaces;
   155   if (!get_interfaces(&network_interfaces)) {
   156     return;
   157   }
   158   if (LogJFR && Verbose) tty->print_cr("Reporting network utilization");
   159   static JfrTicks last_sample_instant;
   160   const JfrTicks cur_time = JfrTicks::now();
   161   const JfrTickspan interval = last_sample_instant == 0 ? cur_time - cur_time : cur_time - last_sample_instant;
   162   last_sample_instant = cur_time;
   163   for (NetworkInterface *cur = network_interfaces; cur != NULL; cur = cur->next()) {
   164     InterfaceEntry& entry = get_entry(cur);
   165     if (interval.value() > 0) {
   166       const uint64_t current_bytes_in = cur->get_bytes_in();
   167       const uint64_t current_bytes_out = cur->get_bytes_out();
   168       const uint64_t read_rate = rate_per_second(current_bytes_in, entry.bytes_in, interval);
   169       const uint64_t write_rate = rate_per_second(current_bytes_out, entry.bytes_out, interval);
   170       if (read_rate > 0 || write_rate > 0) {
   171         entry.in_use = true;
   172         EventNetworkUtilization event(UNTIMED);
   173         event.set_starttime(cur_time);
   174         event.set_endtime(cur_time);
   175         event.set_networkInterface(entry.id);
   176         event.set_readRate(8 * read_rate);
   177         event.set_writeRate(8 * write_rate);
   178         event.commit();
   179       }
   180       // update existing entry with new values
   181       entry.bytes_in = current_bytes_in;
   182       entry.bytes_out = current_bytes_out;
   183     }
   184   }
   186   static bool is_serializer_registered = false;
   187   if (!is_serializer_registered) {
   188     is_serializer_registered = register_network_interface_name_serializer();
   189   }
   190 }

mercurial