Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/src/share/vm/jfr/periodic/jfrNetworkUtilization.cpp
38920 views
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
*/
24
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"
35
36
struct InterfaceEntry {
37
char* name;
38
traceid id;
39
uint64_t bytes_in;
40
uint64_t bytes_out;
41
bool in_use;
42
};
43
44
static GrowableArray<InterfaceEntry>* _interfaces = NULL;
45
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
}
55
56
static InterfaceEntry& new_entry(const NetworkInterface* iface, GrowableArray<InterfaceEntry>* interfaces) {
57
assert(iface != NULL, "invariant");
58
assert(interfaces != NULL, "invariant");
59
60
// single threaded premise
61
static traceid interface_id = 0;
62
63
const char* name = iface->get_name();
64
assert(name != NULL, "invariant");
65
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
}
76
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
}
83
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;
88
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
}
99
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
}
109
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
}
118
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
};
143
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
}
151
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
}
185
186
static bool is_serializer_registered = false;
187
if (!is_serializer_registered) {
188
is_serializer_registered = register_network_interface_name_serializer();
189
}
190
}
191
192