src/hotspot/share/jfr/periodic/jfrNetworkUtilization.cpp
changeset 58863 c16ac7a2eba4
parent 53013 c8b2a408628b
equal deleted inserted replaced
58861:2c3cc4b01880 58863:c16ac7a2eba4
     1 /*
     1 /*
     2  * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     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
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.
     7  * published by the Free Software Foundation.
    37 struct InterfaceEntry {
    37 struct InterfaceEntry {
    38   char* name;
    38   char* name;
    39   traceid id;
    39   traceid id;
    40   uint64_t bytes_in;
    40   uint64_t bytes_in;
    41   uint64_t bytes_out;
    41   uint64_t bytes_out;
    42   bool in_use;
    42   mutable bool written;
    43 };
    43 };
    44 
    44 
    45 static GrowableArray<InterfaceEntry>* _interfaces = NULL;
    45 static GrowableArray<InterfaceEntry>* _interfaces = NULL;
    46 
    46 
    47 void JfrNetworkUtilization::destroy() {
    47 void JfrNetworkUtilization::destroy() {
    69   entry.name = NEW_C_HEAP_ARRAY(char, length + 1, mtInternal);
    69   entry.name = NEW_C_HEAP_ARRAY(char, length + 1, mtInternal);
    70   strncpy(entry.name, name, length + 1);
    70   strncpy(entry.name, name, length + 1);
    71   entry.id = ++interface_id;
    71   entry.id = ++interface_id;
    72   entry.bytes_in = iface->get_bytes_in();
    72   entry.bytes_in = iface->get_bytes_in();
    73   entry.bytes_out = iface->get_bytes_out();
    73   entry.bytes_out = iface->get_bytes_out();
    74   entry.in_use = false;
    74   entry.written = false;
    75   return _interfaces->at(_interfaces->append(entry));
    75   return _interfaces->at(_interfaces->append(entry));
    76 }
    76 }
    77 
    77 
    78 static GrowableArray<InterfaceEntry>* get_interfaces() {
    78 static GrowableArray<InterfaceEntry>* get_interfaces() {
    79   if (_interfaces == NULL) {
    79   if (_interfaces == NULL) {
   106     return 0;
   106     return 0;
   107   }
   107   }
   108   return ((current - old) * NANOSECS_PER_SEC) / interval.nanoseconds();
   108   return ((current - old) * NANOSECS_PER_SEC) / interval.nanoseconds();
   109 }
   109 }
   110 
   110 
       
   111 class JfrNetworkInterfaceName : public JfrSerializer {
       
   112  public:
       
   113    void serialize(JfrCheckpointWriter& writer) {} // we write each constant lazily
       
   114 
       
   115    void on_rotation() {
       
   116      for (int i = 0; i < _interfaces->length(); ++i) {
       
   117        const InterfaceEntry& entry = _interfaces->at(i);
       
   118        if (entry.written) {
       
   119          entry.written = false;
       
   120        }
       
   121      }
       
   122    }
       
   123 };
       
   124 
       
   125 static bool register_network_interface_name_serializer() {
       
   126   assert(_interfaces != NULL, "invariant");
       
   127   return JfrSerializer::register_serializer(TYPE_NETWORKINTERFACENAME,
       
   128     false, // disallow caching; we want a callback every rotation
       
   129     new JfrNetworkInterfaceName());
       
   130 }
       
   131 
       
   132 static void write_interface_constant(const InterfaceEntry& entry) {
       
   133   if (entry.written) {
       
   134     return;
       
   135   }
       
   136   JfrCheckpointWriter writer;
       
   137   writer.write_type(TYPE_NETWORKINTERFACENAME);
       
   138   writer.write_count(1);
       
   139   writer.write_key(entry.id);
       
   140   writer.write(entry.name);
       
   141   entry.written = true;
       
   142 }
       
   143 
   111 static bool get_interfaces(NetworkInterface** network_interfaces) {
   144 static bool get_interfaces(NetworkInterface** network_interfaces) {
   112   const int ret_val = JfrOSInterface::network_utilization(network_interfaces);
   145   const int ret_val = JfrOSInterface::network_utilization(network_interfaces);
   113   if (ret_val == OS_ERR) {
   146   if (ret_val == OS_ERR) {
   114     log_debug(jfr, system)("Unable to generate network utilization events");
   147     log_debug(jfr, system)("Unable to generate network utilization events");
   115     return false;
   148     return false;
   116   }
   149   }
   117   return ret_val != FUNCTIONALITY_NOT_IMPLEMENTED;
   150   return ret_val != FUNCTIONALITY_NOT_IMPLEMENTED;
   118 }
       
   119 
       
   120 class JfrNetworkInterfaceName : public JfrSerializer {
       
   121  public:
       
   122   void serialize(JfrCheckpointWriter& writer) {
       
   123     assert(_interfaces != NULL, "invariant");
       
   124     const JfrCheckpointContext ctx = writer.context();
       
   125     const intptr_t count_offset = writer.reserve(sizeof(u4)); // Don't know how many yet
       
   126     int active_interfaces = 0;
       
   127     for (int i = 0; i < _interfaces->length(); ++i) {
       
   128       InterfaceEntry& entry = _interfaces->at(i);
       
   129       if (entry.in_use) {
       
   130         entry.in_use = false;
       
   131         writer.write_key(entry.id);
       
   132         writer.write(entry.name);
       
   133         ++active_interfaces;
       
   134       }
       
   135     }
       
   136     if (active_interfaces == 0) {
       
   137       // nothing to write, restore context
       
   138       writer.set_context(ctx);
       
   139       return;
       
   140     }
       
   141     writer.write_count(active_interfaces, count_offset);
       
   142   }
       
   143 };
       
   144 
       
   145 static bool register_network_interface_name_serializer() {
       
   146   assert(_interfaces != NULL, "invariant");
       
   147   return JfrSerializer::register_serializer(TYPE_NETWORKINTERFACENAME,
       
   148                                             false, // require safepoint
       
   149                                             false, // disallow caching; we want a callback every rotation
       
   150                                             new JfrNetworkInterfaceName());
       
   151 }
   151 }
   152 
   152 
   153 void JfrNetworkUtilization::send_events() {
   153 void JfrNetworkUtilization::send_events() {
   154   ResourceMark rm;
   154   ResourceMark rm;
   155   NetworkInterface* network_interfaces;
   155   NetworkInterface* network_interfaces;
   167       const uint64_t current_bytes_in = cur->get_bytes_in();
   167       const uint64_t current_bytes_in = cur->get_bytes_in();
   168       const uint64_t current_bytes_out = cur->get_bytes_out();
   168       const uint64_t current_bytes_out = cur->get_bytes_out();
   169       const uint64_t read_rate = rate_per_second(current_bytes_in, entry.bytes_in, interval);
   169       const uint64_t read_rate = rate_per_second(current_bytes_in, entry.bytes_in, interval);
   170       const uint64_t write_rate = rate_per_second(current_bytes_out, entry.bytes_out, interval);
   170       const uint64_t write_rate = rate_per_second(current_bytes_out, entry.bytes_out, interval);
   171       if (read_rate > 0 || write_rate > 0) {
   171       if (read_rate > 0 || write_rate > 0) {
   172         entry.in_use = true;
   172         write_interface_constant(entry);
   173         EventNetworkUtilization event(UNTIMED);
   173         EventNetworkUtilization event(UNTIMED);
   174         event.set_starttime(cur_time);
   174         event.set_starttime(cur_time);
   175         event.set_endtime(cur_time);
   175         event.set_endtime(cur_time);
   176         event.set_networkInterface(entry.id);
   176         event.set_networkInterface(entry.id);
   177         event.set_readRate(8 * read_rate);
   177         event.set_readRate(8 * read_rate);