diff --git a/src/jdk.jfr/share/classes/jdk/jfr/events/EventConfigurations.java b/src/jdk.jfr/share/classes/jdk/jfr/events/EventConfigurations.java
index 383feaee73ef8..ace6c1d84b4b4 100644
--- a/src/jdk.jfr/share/classes/jdk/jfr/events/EventConfigurations.java
+++ b/src/jdk.jfr/share/classes/jdk/jfr/events/EventConfigurations.java
@@ -31,6 +31,8 @@ public final class EventConfigurations {
public static final EventConfiguration SOCKET_READ = JVMSupport.getConfiguration(SocketReadEvent.class);
public static final EventConfiguration SOCKET_WRITE = JVMSupport.getConfiguration(SocketWriteEvent.class);
public static final EventConfiguration FILE_READ = JVMSupport.getConfiguration(FileReadEvent.class);
+ public static final EventConfiguration FILE_WRITE_IO_STATISTICS = JVMSupport.getConfiguration(FileWriteIOStatisticsEvent.class);
+ public static final EventConfiguration FILE_READ_IO_STATISTICS = JVMSupport.getConfiguration(FileReadIOStatisticsEvent.class);
public static final EventConfiguration FILE_WRITE = JVMSupport.getConfiguration(FileWriteEvent.class);
public static final EventConfiguration FILE_FORCE = JVMSupport.getConfiguration(FileForceEvent.class);
public static final EventConfiguration ERROR_THROWN = JVMSupport.getConfiguration(ErrorThrownEvent.class);
diff --git a/src/jdk.jfr/share/classes/jdk/jfr/events/FileReadIOStatisticsEvent.java b/src/jdk.jfr/share/classes/jdk/jfr/events/FileReadIOStatisticsEvent.java
new file mode 100644
index 0000000000000..577869b640a7e
--- /dev/null
+++ b/src/jdk.jfr/share/classes/jdk/jfr/events/FileReadIOStatisticsEvent.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.jfr.events;
+
+import jdk.jfr.Category;
+import jdk.jfr.Description;
+import jdk.jfr.Label;
+import jdk.jfr.Name;
+import jdk.jfr.StackTrace;
+import jdk.jfr.internal.Type;
+import java.util.concurrent.atomic.AtomicLong;
+
+@Name(Type.EVENT_NAME_PREFIX + "FileReadIOStatistics")
+@Label("FileReadIO Statistics")
+@Category({ "Java Application", "Statistics" })
+@Description("Read Rate from the FileInputStream, FileChannelImpl, RandomAccessFile")
+@StackTrace(false)
+public final class FileReadIOStatisticsEvent extends AbstractJDKEvent {
+
+ @Label("Read Rate (Bytes per Sec)")
+ public long readRate;
+
+ @Label("Total Accumulated Read Bytes")
+ public long accRead;
+
+}
\ No newline at end of file
diff --git a/src/jdk.jfr/share/classes/jdk/jfr/events/FileWriteIOStatisticsEvent.java b/src/jdk.jfr/share/classes/jdk/jfr/events/FileWriteIOStatisticsEvent.java
new file mode 100644
index 0000000000000..268009df0e5b5
--- /dev/null
+++ b/src/jdk.jfr/share/classes/jdk/jfr/events/FileWriteIOStatisticsEvent.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.jfr.events;
+
+import jdk.jfr.Category;
+import jdk.jfr.Description;
+import jdk.jfr.Label;
+import jdk.jfr.Name;
+import jdk.jfr.StackTrace;
+import jdk.jfr.internal.Type;
+import java.util.concurrent.atomic.AtomicLong;
+
+@Name(Type.EVENT_NAME_PREFIX + "FileWriteIOStatistics")
+@Label("FileWriteIO Statistics")
+@Category({ "Java Application", "Statistics" })
+@Description("Write Rate from the FileOutputStream, FileChannelImpl, RandomAccessFile")
+@StackTrace(false)
+public final class FileWriteIOStatisticsEvent extends AbstractJDKEvent {
+
+ @Label("Write Rate (Bytes per Sec)")
+ public long writeRate;
+
+ @Label("Total Accumulated Write Bytes")
+ public long accWrite;
+
+}
\ No newline at end of file
diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/FileChannelImplInstrumentor.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/FileChannelImplInstrumentor.java
index d0d8d9b4509e1..155f06f54d88f 100644
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/FileChannelImplInstrumentor.java
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/FileChannelImplInstrumentor.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -66,18 +66,20 @@ public void force(boolean metaData) throws IOException {
@JIInstrumentationMethod
public int read(ByteBuffer dst) throws IOException {
- EventConfiguration eventConfiguration = EventConfigurations.FILE_READ;
- if (!eventConfiguration.isEnabled()) {
+ EventConfiguration fileReadEventConfiguration = EventConfigurations.FILE_READ;
+ EventConfiguration fileReadIOStatisticsEventConfiguration = EventConfigurations.FILE_READ_IO_STATISTICS;
+ if (!fileReadEventConfiguration.isEnabled() && !fileReadIOStatisticsEventConfiguration.isEnabled()) {
return read(dst);
}
int bytesRead = 0;
long start = 0;
+ long duration = 0;
try {
start = EventConfiguration.timestamp();
bytesRead = read(dst);
} finally {
- long duration = EventConfiguration.timestamp() - start;
- if (eventConfiguration.shouldCommit(duration)) {
+ duration = EventConfiguration.timestamp() - start;
+ if (fileReadEventConfiguration.shouldCommit(duration)) {
if (bytesRead < 0) {
FileReadEvent.commit(start, duration, path, 0L, true);
} else {
@@ -85,47 +87,57 @@ public int read(ByteBuffer dst) throws IOException {
}
}
}
+ if(fileReadIOStatisticsEventConfiguration.isEnabled()){
+ FileIOStatistics.addTotalReadBytesForPeriod(((bytesRead < 0) ? 0 : bytesRead), duration);
+ }
return bytesRead;
}
@JIInstrumentationMethod
public int read(ByteBuffer dst, long position) throws IOException {
- EventConfiguration eventConfiguration = EventConfigurations.FILE_READ;
- if (!eventConfiguration.isEnabled()) {
+ EventConfiguration fileReadEventConfiguration = EventConfigurations.FILE_READ;
+ EventConfiguration fileReadIOStatisticsEventConfiguration = EventConfigurations.FILE_READ_IO_STATISTICS;
+ if (!fileReadEventConfiguration.isEnabled() && !fileReadIOStatisticsEventConfiguration.isEnabled()) {
return read(dst, position);
}
int bytesRead = 0;
long start = 0;
+ long duration = 0;
try {
start = EventConfiguration.timestamp();
bytesRead = read(dst, position);
} finally {
- long duration = EventConfiguration.timestamp() - start;
- if (eventConfiguration.shouldCommit(duration)) {
+ duration = EventConfiguration.timestamp() - start;
+ if (fileReadEventConfiguration.shouldCommit(duration)) {
if (bytesRead < 0) {
FileReadEvent.commit(start, duration, path, 0L, true);
} else {
FileReadEvent.commit(start, duration, path, bytesRead, false);
}
}
+ }
+ if(fileReadIOStatisticsEventConfiguration.isEnabled()){
+ FileIOStatistics.addTotalReadBytesForPeriod(((bytesRead < 0) ? 0 : bytesRead), duration);
}
return bytesRead;
}
@JIInstrumentationMethod
public long read(ByteBuffer[] dsts, int offset, int length) throws IOException {
- EventConfiguration eventConfiguration = EventConfigurations.FILE_READ;
- if (!eventConfiguration.isEnabled()) {
+ EventConfiguration fileReadEventConfiguration = EventConfigurations.FILE_READ;
+ EventConfiguration fileReadIOStatisticsEventConfiguration = EventConfigurations.FILE_READ_IO_STATISTICS;
+ if (!fileReadEventConfiguration.isEnabled() && !fileReadIOStatisticsEventConfiguration.isEnabled()) {
return read(dsts, offset, length);
}
long bytesRead = 0;
long start = 0;
+ long duration = 0;
try {
start = EventConfiguration.timestamp();
bytesRead = read(dsts, offset, length);
} finally {
- long duration = EventConfiguration.timestamp() - start;
- if (eventConfiguration.shouldCommit(duration)) {
+ duration = EventConfiguration.timestamp() - start;
+ if (fileReadEventConfiguration.shouldCommit(duration)) {
if (bytesRead < 0) {
FileReadEvent.commit(start, duration, path, 0L, true);
} else {
@@ -133,70 +145,88 @@ public long read(ByteBuffer[] dsts, int offset, int length) throws IOException {
}
}
}
+ if(fileReadIOStatisticsEventConfiguration.isEnabled()){
+ FileIOStatistics.addTotalReadBytesForPeriod(((bytesRead < 0) ? 0 : bytesRead), duration);
+ }
return bytesRead;
}
@JIInstrumentationMethod
public int write(ByteBuffer src) throws IOException {
- EventConfiguration eventConfiguration = EventConfigurations.FILE_WRITE;
- if (!eventConfiguration.isEnabled()) {
+ EventConfiguration fileWriteEventConfiguration = EventConfigurations.FILE_WRITE;
+ EventConfiguration fileWriteIOStatisticsEventConfiguration = EventConfigurations.FILE_WRITE_IO_STATISTICS;
+ if (!fileWriteEventConfiguration.isEnabled() && !fileWriteIOStatisticsEventConfiguration.isEnabled()) {
return write(src);
- }
+ }
int bytesWritten = 0;
long start = 0;
+ long duration = 0;
try {
start = EventConfiguration.timestamp();
bytesWritten = write(src);
} finally {
- long duration = EventConfiguration.timestamp() - start;
- if (eventConfiguration.shouldCommit(duration)) {
+ duration = EventConfiguration.timestamp() - start;
+ if (fileWriteEventConfiguration.shouldCommit(duration)) {
long bytes = bytesWritten > 0 ? bytesWritten : 0;
FileWriteEvent.commit(start, duration, path, bytes);
}
}
+ if(fileWriteIOStatisticsEventConfiguration.isEnabled()){
+ FileIOStatistics.addTotalWriteBytesForPeriod(((bytesWritten > 0) ? bytesWritten : 0), duration);
+ }
return bytesWritten;
}
@JIInstrumentationMethod
public int write(ByteBuffer src, long position) throws IOException {
- EventConfiguration eventConfiguration = EventConfigurations.FILE_WRITE;
- if (!eventConfiguration.isEnabled()) {
+ EventConfiguration fileWriteEventConfiguration = EventConfigurations.FILE_WRITE;
+ EventConfiguration fileWriteIOStatisticsEventConfiguration = EventConfigurations.FILE_WRITE_IO_STATISTICS;
+ if (!fileWriteEventConfiguration.isEnabled() && !fileWriteIOStatisticsEventConfiguration.isEnabled()) {
return write(src, position);
}
-
int bytesWritten = 0;
long start = 0;
+ long duration = 0;
try {
start = EventConfiguration.timestamp();
bytesWritten = write(src, position);
} finally {
- long duration = EventConfiguration.timestamp() - start;
- if (eventConfiguration.shouldCommit(duration)) {
+ duration = EventConfiguration.timestamp() - start;
+ if (fileWriteEventConfiguration.shouldCommit(duration)) {
long bytes = bytesWritten > 0 ? bytesWritten : 0;
FileWriteEvent.commit(start, duration, path, bytes);
}
}
+ if(fileWriteIOStatisticsEventConfiguration.isEnabled()){
+ FileIOStatistics.addTotalWriteBytesForPeriod(((bytesWritten > 0) ? bytesWritten : 0), duration);
+ }
+
return bytesWritten;
}
@JIInstrumentationMethod
public long write(ByteBuffer[] srcs, int offset, int length) throws IOException {
- EventConfiguration eventConfiguration = EventConfigurations.FILE_WRITE;
- if (!eventConfiguration.isEnabled()) {
+ EventConfiguration fileWriteEventConfiguration = EventConfigurations.FILE_WRITE;
+ EventConfiguration fileWriteIOStatisticsEventConfiguration = EventConfigurations.FILE_WRITE_IO_STATISTICS;
+ if (!fileWriteEventConfiguration.isEnabled() && !fileWriteIOStatisticsEventConfiguration.isEnabled()) {
return write(srcs, offset, length);
}
long bytesWritten = 0;
long start = 0;
+ long duration = 0;
try {
start = EventConfiguration.timestamp();
bytesWritten = write(srcs, offset, length);
} finally {
- long duration = EventConfiguration.timestamp() - start;
- if (eventConfiguration.shouldCommit(duration)) {
+ duration = EventConfiguration.timestamp() - start;
+ if (fileWriteEventConfiguration.shouldCommit(duration)) {
long bytes = bytesWritten > 0 ? bytesWritten : 0;
FileWriteEvent.commit(start, duration, path, bytes);
}
}
+ if(fileWriteIOStatisticsEventConfiguration.isEnabled()){
+ FileIOStatistics.addTotalWriteBytesForPeriod(((bytesWritten > 0) ? bytesWritten : 0), duration);
+ }
return bytesWritten;
}
}
diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/FileIOStatistics.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/FileIOStatistics.java
new file mode 100644
index 0000000000000..da3e1df36fed7
--- /dev/null
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/FileIOStatistics.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.jfr.internal.instrument;
+
+import java.util.concurrent.atomic.AtomicLong;
+
+public final class FileIOStatistics {
+
+ private static AtomicLong totalReadBytesForPeriod = new AtomicLong(0);
+ private static AtomicLong totalReadDuration = new AtomicLong(0);
+ private static AtomicLong totalReadBytesForProcess = new AtomicLong(0);
+ private static AtomicLong totalWriteBytesForProcess = new AtomicLong(0);
+ private static AtomicLong totalWriteBytesForPeriod = new AtomicLong(0);
+ private static AtomicLong totalWriteDuration = new AtomicLong(0);
+
+ public static long getTotalReadBytesForProcess() {
+ return totalReadBytesForProcess.get();
+ }
+
+ public static long getTotalReadDuration() {
+ return totalReadDuration.get();
+ }
+
+ public static long getTotalReadBytesForPeriod() {
+ return totalReadBytesForPeriod.get();
+ }
+
+ public static void addTotalReadBytesForPeriod(long bytesRead, long duration) {
+ totalReadDuration.addAndGet(duration);
+ totalReadBytesForProcess.addAndGet(bytesRead);
+ totalReadBytesForPeriod.addAndGet(bytesRead);
+ }
+
+ /**
+ * Calculates and returns the read rate in bytes per second for the period mentioned in the jfc.
+ *
+ * This method computes the read rate by taking the total number of bytes read
+ * and the total duration of the read operation, then calculates the rate as
+ * bytes per second. If the interval is zero or negative, it returns 0.
+ *
+ * @return The read rate in bytes per second.
+ */
+ public static long getAndResetReadRateForPeriod() {
+ long result = getTotalReadBytesForPeriod();
+ long interval = getTotalReadDuration();
+ totalReadBytesForPeriod.addAndGet(-result);
+ if (interval > 0) {
+ totalReadDuration.addAndGet(-interval);
+ double intervalInSec = (interval * 1.0 / 1_000_000_000);
+ long rRate = (long) (result / intervalInSec);
+ return rRate;
+ }
+ return 0;
+ }
+
+ public static long getTotalWriteBytesForProcess() {
+ return totalWriteBytesForProcess.get();
+ }
+
+ public static long getTotalWriteDuration() {
+ return totalWriteDuration.get();
+ }
+
+ public static long getTotalWriteBytesForPeriod() {
+ return totalWriteBytesForPeriod.get();
+ }
+
+ public static long addTotalWriteBytesForPeriod(long bytesWritten, long duration) {
+ totalWriteDuration.addAndGet(duration);
+ totalWriteBytesForProcess.addAndGet(bytesWritten);
+ return totalWriteBytesForPeriod.addAndGet(bytesWritten);
+ }
+
+ /**
+ * Calculates and returns the write rate in bytes per second for the period mentioned in the jfc.
+ *
+ * This method computes the write rate by taking the total number of bytes written
+ * and the total duration of the write operation, then calculates the rate as
+ * bytes per second. If the interval is zero or negative, it returns 0.
+ *
+ * @return The write rate in bytes per second.
+ */
+ public static long getAndResetWriteRateForPeriod() {
+ long result = getTotalWriteBytesForPeriod();
+ long interval = getTotalWriteDuration();
+ totalWriteBytesForPeriod.addAndGet(-result);
+ if (interval > 0) {
+ totalWriteDuration.addAndGet(-interval);
+ double intervalInSec = (interval * 1.0 / 1_000_000_000);
+ long wRate = (long) (result / intervalInSec);
+ return wRate;
+ }
+ return 0;
+ }
+}
diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/FileInputStreamInstrumentor.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/FileInputStreamInstrumentor.java
index 1d1ccb3bcb232..bcfcfdf6ec732 100644
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/FileInputStreamInstrumentor.java
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/FileInputStreamInstrumentor.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -29,6 +29,7 @@
import jdk.jfr.events.EventConfigurations;
import jdk.jfr.events.FileReadEvent;
+import jdk.jfr.internal.instrument.FileIOStatistics;
import jdk.jfr.internal.event.EventConfiguration;
/**
@@ -44,14 +45,16 @@ private FileInputStreamInstrumentor() {
@JIInstrumentationMethod
public int read() throws IOException {
- EventConfiguration eventConfiguration = EventConfigurations.FILE_READ;
- if (!eventConfiguration.isEnabled()) {
+ EventConfiguration fileReadEventConfiguration = EventConfigurations.FILE_READ;
+ EventConfiguration fileReadIOStatisticsEventConfiguration = EventConfigurations.FILE_READ_IO_STATISTICS;
+ if (!fileReadEventConfiguration.isEnabled() && !fileReadIOStatisticsEventConfiguration.isEnabled()) {
return read();
}
int result = 0;
boolean endOfFile = false;
long bytesRead = 0;
long start = 0;
+ long duration = 0;
try {
start = EventConfiguration.timestamp();
result = read();
@@ -61,28 +64,35 @@ public int read() throws IOException {
bytesRead = 1;
}
} finally {
- long duration = EventConfiguration.timestamp() - start;
- if (eventConfiguration.shouldCommit(duration)) {
+ duration = EventConfiguration.timestamp() - start;
+ if (fileReadEventConfiguration.shouldCommit(duration)) {
FileReadEvent.commit(start, duration, path, bytesRead, endOfFile);
}
}
+
+ if(fileReadIOStatisticsEventConfiguration.isEnabled()){
+ FileIOStatistics.addTotalReadBytesForPeriod(bytesRead, duration);
+ }
+
return result;
}
@JIInstrumentationMethod
public int read(byte b[]) throws IOException {
- EventConfiguration eventConfiguration = EventConfigurations.FILE_READ;
- if (!eventConfiguration.isEnabled()) {
+ EventConfiguration fileReadEventConfiguration = EventConfigurations.FILE_READ;
+ EventConfiguration fileReadIOStatisticsEventConfiguration = EventConfigurations.FILE_READ_IO_STATISTICS;
+ if (!fileReadEventConfiguration.isEnabled() && !fileReadIOStatisticsEventConfiguration.isEnabled()) {
return read(b);
}
int bytesRead = 0;
long start = 0;
+ long duration = 0;
try {
start = EventConfiguration.timestamp();
bytesRead = read(b);
} finally {
- long duration = EventConfiguration.timestamp() - start;
- if (eventConfiguration.shouldCommit(duration)) {
+ duration = EventConfiguration.timestamp() - start;
+ if (fileReadEventConfiguration.shouldCommit(duration)) {
if (bytesRead < 0) {
FileReadEvent.commit(start, duration, path, 0L, true);
} else {
@@ -90,23 +100,30 @@ public int read(byte b[]) throws IOException {
}
}
}
+
+ if(fileReadIOStatisticsEventConfiguration.isEnabled()){
+ FileIOStatistics.addTotalReadBytesForPeriod(((bytesRead < 0) ? 0 : bytesRead), duration);
+ }
+
return bytesRead;
}
@JIInstrumentationMethod
public int read(byte b[], int off, int len) throws IOException {
- EventConfiguration eventConfiguration = EventConfigurations.FILE_READ;
- if (!eventConfiguration.isEnabled()) {
+ EventConfiguration fileReadEventConfiguration = EventConfigurations.FILE_READ;
+ EventConfiguration fileReadIOStatisticsEventConfiguration = EventConfigurations.FILE_READ_IO_STATISTICS;
+ if (!fileReadEventConfiguration.isEnabled() && !fileReadIOStatisticsEventConfiguration.isEnabled()) {
return read(b, off, len);
}
int bytesRead = 0;
long start = 0;
+ long duration = 0;
try {
start = EventConfiguration.timestamp();
bytesRead = read(b, off, len);
} finally {
- long duration = EventConfiguration.timestamp() - start;
- if (eventConfiguration.shouldCommit(duration)) {
+ duration = EventConfiguration.timestamp() - start;
+ if (fileReadEventConfiguration.shouldCommit(duration)) {
if (bytesRead < 0) {
FileReadEvent.commit(start, duration, path, 0L, true);
} else {
@@ -114,6 +131,10 @@ public int read(byte b[], int off, int len) throws IOException {
}
}
}
+ if(fileReadIOStatisticsEventConfiguration.isEnabled()){
+ FileIOStatistics.addTotalReadBytesForPeriod(((bytesRead < 0) ? 0 : bytesRead), duration);
+ }
+
return bytesRead;
}
}
diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/FileOutputStreamInstrumentor.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/FileOutputStreamInstrumentor.java
index 2e9e750df9d8a..1660164103b84 100644
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/FileOutputStreamInstrumentor.java
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/FileOutputStreamInstrumentor.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -44,64 +44,81 @@ private FileOutputStreamInstrumentor() {
@JIInstrumentationMethod
public void write(int b) throws IOException {
- EventConfiguration eventConfiguration = EventConfigurations.FILE_WRITE;
- if (!eventConfiguration.isEnabled()) {
+ EventConfiguration fileWriteEventConfiguration = EventConfigurations.FILE_WRITE;
+ EventConfiguration fileWriteIOStatisticsEventConfiguration = EventConfigurations.FILE_WRITE_IO_STATISTICS;
+ if (!fileWriteEventConfiguration.isEnabled() && !fileWriteIOStatisticsEventConfiguration.isEnabled()) {
write(b);
return;
}
long bytesWritten = 0;
long start = 0;
+ long duration = 0;
try {
start = EventConfiguration.timestamp();
write(b);
bytesWritten = 1;
} finally {
- long duration = EventConfiguration.timestamp() - start;
- if (eventConfiguration.shouldCommit(duration)) {
+ duration = EventConfiguration.timestamp() - start;
+ if (fileWriteEventConfiguration.shouldCommit(duration)) {
FileWriteEvent.commit(start, duration, path, bytesWritten);
}
}
+
+ if (fileWriteIOStatisticsEventConfiguration.isEnabled()) {
+ FileIOStatistics.addTotalWriteBytesForPeriod(bytesWritten, duration);
+ }
}
@JIInstrumentationMethod
public void write(byte b[]) throws IOException {
- EventConfiguration eventConfiguration = EventConfigurations.FILE_WRITE;
- if (!eventConfiguration.isEnabled()) {
+ EventConfiguration fileWriteEventConfiguration = EventConfigurations.FILE_WRITE;
+ EventConfiguration fileWriteIOStatisticsEventConfiguration = EventConfigurations.FILE_WRITE_IO_STATISTICS;
+ if (!fileWriteEventConfiguration.isEnabled() && !fileWriteIOStatisticsEventConfiguration.isEnabled()) {
write(b);
return;
}
long bytesWritten = 0;
long start = 0;
+ long duration = 0;
try {
start = EventConfiguration.timestamp();
write(b);
bytesWritten = b.length;
} finally {
- long duration = EventConfiguration.timestamp() - start;
- if (eventConfiguration.shouldCommit(duration)) {
+ duration = EventConfiguration.timestamp() - start;
+ if (fileWriteEventConfiguration.shouldCommit(duration)) {
FileWriteEvent.commit(start, duration, path, bytesWritten);
}
}
+ if (fileWriteIOStatisticsEventConfiguration.isEnabled()) {
+ FileIOStatistics.addTotalWriteBytesForPeriod(bytesWritten, duration);
+ }
}
@JIInstrumentationMethod
public void write(byte b[], int off, int len) throws IOException {
- EventConfiguration eventConfiguration = EventConfigurations.FILE_WRITE;
- if (!eventConfiguration.isEnabled()) {
+ EventConfiguration fileWriteEventConfiguration = EventConfigurations.FILE_WRITE;
+ EventConfiguration fileWriteIOStatisticsEventConfiguration = EventConfigurations.FILE_WRITE_IO_STATISTICS;
+ if (!fileWriteEventConfiguration.isEnabled() && !fileWriteIOStatisticsEventConfiguration.isEnabled()) {
write(b, off, len);
return;
}
long bytesWritten = 0;
long start = 0;
+ long duration = 0;
try {
start = EventConfiguration.timestamp();
write(b, off, len);
bytesWritten = len;
} finally {
- long duration = EventConfiguration.timestamp() - start;
- if (eventConfiguration.shouldCommit(duration)) {
+ duration = EventConfiguration.timestamp() - start;
+ if (fileWriteEventConfiguration.shouldCommit(duration)) {
FileWriteEvent.commit(start, duration, path, bytesWritten);
}
}
+ if (fileWriteIOStatisticsEventConfiguration.isEnabled()) {
+ FileIOStatistics.addTotalWriteBytesForPeriod(bytesWritten, duration);
+ }
+
}
}
diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/JDKEvents.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/JDKEvents.java
index 9405dfff8e0e7..9cf87eb387162 100644
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/JDKEvents.java
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/JDKEvents.java
@@ -25,6 +25,7 @@
package jdk.jfr.internal.instrument;
+import java.time.Period;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
@@ -45,6 +46,8 @@
import jdk.jfr.events.FileForceEvent;
import jdk.jfr.events.FileReadEvent;
import jdk.jfr.events.FileWriteEvent;
+import jdk.jfr.events.FileReadIOStatisticsEvent;
+import jdk.jfr.events.FileWriteIOStatisticsEvent;
import jdk.jfr.events.DeserializationEvent;
import jdk.jfr.events.InitialSecurityPropertyEvent;
import jdk.jfr.events.ProcessStartEvent;
@@ -89,6 +92,8 @@ public final class JDKEvents {
FileForceEvent.class,
FileReadEvent.class,
FileWriteEvent.class,
+ FileReadIOStatisticsEvent.class,
+ FileWriteIOStatisticsEvent.class,
SocketReadEvent.class,
SocketWriteEvent.class,
ExceptionThrownEvent.class,
@@ -133,6 +138,8 @@ public final class JDKEvents {
private static final Runnable emitContainerMemoryUsage = JDKEvents::emitContainerMemoryUsage;
private static final Runnable emitContainerIOUsage = JDKEvents::emitContainerIOUsage;
private static final Runnable emitInitialSecurityProperties = JDKEvents::emitInitialSecurityProperties;
+ private static final Runnable emitFileReadIOStatistics = JDKEvents::emitFileReadIOStatistics;
+ private static final Runnable emitFileWriteIOStatistics = JDKEvents::emitFileWriteIOStatistics;
private static Metrics containerMetrics = null;
private static boolean initializationTriggered;
@@ -149,6 +156,8 @@ public static synchronized void initialize() {
PeriodicEvents.addJDKEvent(ExceptionStatisticsEvent.class, emitExceptionStatistics);
PeriodicEvents.addJDKEvent(DirectBufferStatisticsEvent.class, emitDirectBufferStatistics);
PeriodicEvents.addJDKEvent(InitialSecurityPropertyEvent.class, emitInitialSecurityProperties);
+ PeriodicEvents.addJDKEvent(FileReadIOStatisticsEvent.class, emitFileReadIOStatistics);
+ PeriodicEvents.addJDKEvent(FileWriteIOStatisticsEvent.class, emitFileWriteIOStatistics);
initializeContainerEvents();
initializationTriggered = true;
@@ -265,6 +274,26 @@ private static void emitContainerCPUThrottling() {
}
}
+ private static void emitFileReadIOStatistics() {
+ FileReadIOStatisticsEvent t = new FileReadIOStatisticsEvent();
+ if (FileIOStatistics.getTotalReadBytesForProcess() > 0) {
+ t.begin();
+ t.accRead = FileIOStatistics.getTotalReadBytesForProcess();
+ t.readRate = FileIOStatistics.getAndResetReadRateForPeriod();
+ t.commit();
+ }
+ }
+
+ private static void emitFileWriteIOStatistics() {
+ FileWriteIOStatisticsEvent t = new FileWriteIOStatisticsEvent();
+ if (FileIOStatistics.getTotalWriteBytesForProcess() > 0) {
+ t.begin();
+ t.accWrite = FileIOStatistics.getTotalWriteBytesForProcess();
+ t.writeRate = FileIOStatistics.getAndResetWriteRateForPeriod();
+ t.commit();
+ }
+ }
+
@SuppressWarnings("deprecation")
public static byte[] retransformCallback(Class> klass, byte[] oldBytes) throws Throwable {
if (java.lang.Throwable.class == klass) {
@@ -293,6 +322,8 @@ public static void remove() {
PeriodicEvents.removeEvent(emitExceptionStatistics);
PeriodicEvents.removeEvent(emitDirectBufferStatistics);
PeriodicEvents.removeEvent(emitInitialSecurityProperties);
+ PeriodicEvents.removeEvent(emitFileReadIOStatistics);
+ PeriodicEvents.removeEvent(emitFileWriteIOStatistics);
PeriodicEvents.removeEvent(emitContainerConfiguration);
PeriodicEvents.removeEvent(emitContainerCPUUsage);
diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/RandomAccessFileInstrumentor.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/RandomAccessFileInstrumentor.java
index 128859358d84b..d82158583106d 100644
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/RandomAccessFileInstrumentor.java
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/RandomAccessFileInstrumentor.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -45,14 +45,16 @@ private RandomAccessFileInstrumentor() {
@JIInstrumentationMethod
public int read() throws IOException {
- EventConfiguration eventConfiguration = EventConfigurations.FILE_READ;
- if (!eventConfiguration.isEnabled()) {
+ EventConfiguration fileReadEventConfiguration = EventConfigurations.FILE_READ;
+ EventConfiguration fileReadIOStatisticsEventConfiguration = EventConfigurations.FILE_READ_IO_STATISTICS;
+ if (!fileReadEventConfiguration.isEnabled() && !fileReadIOStatisticsEventConfiguration.isEnabled()) {
return read();
}
int result = 0;
long bytesRead = 0;
boolean endOfFile = false;
long start = 0;
+ long duration = 0;
try {
start = EventConfiguration.timestamp();
result = read();
@@ -62,28 +64,33 @@ public int read() throws IOException {
bytesRead = 1;
}
} finally {
- long duration = EventConfiguration.timestamp() - start;
- if (eventConfiguration.shouldCommit(duration)) {
+ duration = EventConfiguration.timestamp() - start;
+ if (fileReadEventConfiguration.shouldCommit(duration)) {
FileReadEvent.commit(start, duration, path, bytesRead, endOfFile);
}
}
+ if(fileReadIOStatisticsEventConfiguration.isEnabled()){
+ FileIOStatistics.addTotalReadBytesForPeriod(((result < 0) ? 0 : bytesRead), duration);
+ }
return result;
}
@JIInstrumentationMethod
public int read(byte b[]) throws IOException {
- EventConfiguration eventConfiguration = EventConfigurations.FILE_READ;
- if (!eventConfiguration.isEnabled()) {
+ EventConfiguration fileReadEventConfiguration = EventConfigurations.FILE_READ;
+ EventConfiguration fileReadIOStatisticsEventConfiguration = EventConfigurations.FILE_READ_IO_STATISTICS;
+ if (!fileReadEventConfiguration.isEnabled() && !fileReadIOStatisticsEventConfiguration.isEnabled()) {
return read(b);
}
int bytesRead = 0;
long start = 0;
+ long duration = 0;
try {
start = EventConfiguration.timestamp();
bytesRead = read(b);
} finally {
- long duration = EventConfiguration.timestamp() - start;
- if (eventConfiguration.shouldCommit(duration)) {
+ duration = EventConfiguration.timestamp() - start;
+ if (fileReadEventConfiguration.shouldCommit(duration)) {
if (bytesRead < 0) {
FileReadEvent.commit(start, duration, path, 0L, true);
} else {
@@ -91,23 +98,28 @@ public int read(byte b[]) throws IOException {
}
}
}
+ if(fileReadIOStatisticsEventConfiguration.isEnabled()){
+ FileIOStatistics.addTotalReadBytesForPeriod(((bytesRead < 0) ? 0 : bytesRead), duration);
+ }
return bytesRead;
}
@JIInstrumentationMethod
public int read(byte b[], int off, int len) throws IOException {
- EventConfiguration eventConfiguration = EventConfigurations.FILE_READ;
- if (!eventConfiguration.isEnabled()) {
+ EventConfiguration fileReadEventConfiguration = EventConfigurations.FILE_READ;
+ EventConfiguration fileReadIOStatisticsEventConfiguration = EventConfigurations.FILE_READ_IO_STATISTICS;
+ if (!fileReadEventConfiguration.isEnabled() && !fileReadIOStatisticsEventConfiguration.isEnabled()) {
return read(b, off, len);
}
int bytesRead = 0;
long start = 0;
+ long duration = 0;
try {
start = EventConfiguration.timestamp();
bytesRead = read(b, off, len);
} finally {
- long duration = EventConfiguration.timestamp() - start;
- if (eventConfiguration.shouldCommit(duration)) {
+ duration = EventConfiguration.timestamp() - start;
+ if (fileReadEventConfiguration.shouldCommit(duration)) {
if (bytesRead < 0) {
FileReadEvent.commit(start, duration, path, 0L, true);
} else {
@@ -115,69 +127,87 @@ public int read(byte b[], int off, int len) throws IOException {
}
}
}
+ if(fileReadIOStatisticsEventConfiguration.isEnabled()){
+ FileIOStatistics.addTotalReadBytesForPeriod(((bytesRead < 0) ? 0 : bytesRead), duration);
+ }
return bytesRead;
}
@JIInstrumentationMethod
public void write(int b) throws IOException {
- EventConfiguration eventConfiguration = EventConfigurations.FILE_WRITE;
- if (!eventConfiguration.isEnabled()) {
+ EventConfiguration fileWriteEventConfiguration = EventConfigurations.FILE_WRITE;
+ EventConfiguration fileWriteIOStatisticsEventConfiguration = EventConfigurations.FILE_WRITE_IO_STATISTICS;
+ if (!fileWriteEventConfiguration.isEnabled() && !fileWriteIOStatisticsEventConfiguration.isEnabled()) {
write(b);
return;
}
long bytesWritten = 0;
long start = 0;
+ long duration = 0;
try {
start = EventConfiguration.timestamp();
write(b);
bytesWritten = 1;
} finally {
- long duration = EventConfiguration.timestamp() - start;
- if (eventConfiguration.shouldCommit(duration)) {
+ duration = EventConfiguration.timestamp() - start;
+ if (fileWriteEventConfiguration.shouldCommit(duration)) {
FileWriteEvent.commit(start, duration, path, bytesWritten);
}
}
+ if (fileWriteIOStatisticsEventConfiguration.isEnabled()) {
+ FileIOStatistics.addTotalWriteBytesForPeriod(bytesWritten, duration);
+ }
}
@JIInstrumentationMethod
public void write(byte b[]) throws IOException {
- EventConfiguration eventConfiguration = EventConfigurations.FILE_WRITE;
- if (!eventConfiguration.isEnabled()) {
+ EventConfiguration fileWriteEventConfiguration = EventConfigurations.FILE_WRITE;
+ EventConfiguration fileWriteIOStatisticsEventConfiguration = EventConfigurations.FILE_WRITE_IO_STATISTICS;
+ if (!fileWriteEventConfiguration.isEnabled() && !fileWriteIOStatisticsEventConfiguration.isEnabled()) {
write(b);
return;
}
long bytesWritten = 0;
long start = 0;
+ long duration = 0;
try {
start = EventConfiguration.timestamp();
write(b);
bytesWritten = b.length;
} finally {
- long duration = EventConfiguration.timestamp() - start;
- if (eventConfiguration.shouldCommit(duration)) {
+ duration = EventConfiguration.timestamp() - start;
+ if (fileWriteEventConfiguration.shouldCommit(duration)) {
FileWriteEvent.commit(start, duration, path, bytesWritten);
}
}
+ if (fileWriteIOStatisticsEventConfiguration.isEnabled()) {
+ FileIOStatistics.addTotalWriteBytesForPeriod(bytesWritten, duration);
+ }
}
@JIInstrumentationMethod
public void write(byte b[], int off, int len) throws IOException {
- EventConfiguration eventConfiguration = EventConfigurations.FILE_WRITE;
- if (!eventConfiguration.isEnabled()) {
+ EventConfiguration fileWriteEventConfiguration = EventConfigurations.FILE_WRITE;
+ EventConfiguration fileWriteIOStatisticsEventConfiguration = EventConfigurations.FILE_WRITE_IO_STATISTICS;
+ if (!fileWriteEventConfiguration.isEnabled() && !fileWriteIOStatisticsEventConfiguration.isEnabled()) {
write(b, off, len);
return;
}
long bytesWritten = 0;
long start = 0;
+ long duration = 0;
try {
start = EventConfiguration.timestamp();
write(b, off, len);
bytesWritten = len;
} finally {
- long duration = EventConfiguration.timestamp() - start;
- if (eventConfiguration.shouldCommit(duration)) {
+ duration = EventConfiguration.timestamp() - start;
+ if (fileWriteEventConfiguration.shouldCommit(duration)) {
FileWriteEvent.commit(start, duration, path, bytesWritten);
}
}
+ if (fileWriteIOStatisticsEventConfiguration.isEnabled()) {
+ FileIOStatistics.addTotalWriteBytesForPeriod(bytesWritten, duration);
+ }
}
-}
+}
\ No newline at end of file
diff --git a/src/jdk.jfr/share/conf/jfr/default.jfc b/src/jdk.jfr/share/conf/jfr/default.jfc
index 6b0aa1724c439..60e23d24777a2 100644
--- a/src/jdk.jfr/share/conf/jfr/default.jfc
+++ b/src/jdk.jfr/share/conf/jfr/default.jfc
@@ -734,6 +734,16 @@
20 ms
+
+ false
+ 10 s
+
+
+
+ false
+ 10 s
+
+
true
true
diff --git a/src/jdk.jfr/share/conf/jfr/profile.jfc b/src/jdk.jfr/share/conf/jfr/profile.jfc
index 79ce390052a14..4c0f43f18a919 100644
--- a/src/jdk.jfr/share/conf/jfr/profile.jfc
+++ b/src/jdk.jfr/share/conf/jfr/profile.jfc
@@ -734,6 +734,16 @@
10 ms
+
+ false
+ 10 s
+
+
+
+ false
+ 10 s
+
+
true
true
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/CDSandJFR.java b/test/hotspot/jtreg/runtime/cds/appcds/CDSandJFR.java
index 065786686fa06..e15c97788affd 100644
--- a/test/hotspot/jtreg/runtime/cds/appcds/CDSandJFR.java
+++ b/test/hotspot/jtreg/runtime/cds/appcds/CDSandJFR.java
@@ -41,6 +41,8 @@ public class CDSandJFR {
"jdk/jfr/Event",
"jdk/jfr/events/FileReadEvent",
"jdk/jfr/events/FileWriteEvent",
+ "jdk.jfr/events/FileReadIOStatistics",
+ "jdk.jfr/events/FileWriteIOStatistics",
"jdk/jfr/events/SocketReadEvent",
"jdk/jfr/events/SocketWriteEvent",
"jdk/jfr/events/ExceptionThrownEvent",
diff --git a/test/jdk/jdk/jfr/api/recording/settings/TestSettingsAvailability.java b/test/jdk/jdk/jfr/api/recording/settings/TestSettingsAvailability.java
index dd160881d2edd..f44f998f91cba 100644
--- a/test/jdk/jdk/jfr/api/recording/settings/TestSettingsAvailability.java
+++ b/test/jdk/jdk/jfr/api/recording/settings/TestSettingsAvailability.java
@@ -91,6 +91,8 @@ private static void testKnownSettings() throws Exception {
testSetting(EventNames.JVMInformation, "enabled", "period");
testSetting(EventNames.FileRead, "enabled", "threshold", "stackTrace");
testSetting(EventNames.FileWrite, "enabled", "threshold","stackTrace");
+ testSetting(EventNames.FileReadIOStatistics, "enabled", "period");
+ testSetting(EventNames.FileWriteIOStatistics, "enabled", "period");
testSetting(EventNames.ExceptionStatistics, "enabled", "period");
testSetting(EventNames.SocketRead, "enabled", "threshold", "stackTrace");
testSetting(EventNames.SocketWrite, "enabled", "threshold", "stackTrace");
diff --git a/test/jdk/jdk/jfr/event/io/TestDisabledEvents.java b/test/jdk/jdk/jfr/event/io/TestDisabledEvents.java
index 0b523b80523b8..57896cb106397 100644
--- a/test/jdk/jdk/jfr/event/io/TestDisabledEvents.java
+++ b/test/jdk/jdk/jfr/event/io/TestDisabledEvents.java
@@ -36,6 +36,7 @@
import jdk.jfr.Recording;
import jdk.jfr.consumer.RecordedEvent;
import jdk.test.lib.Utils;
+import jdk.test.lib.jfr.EventNames;
import jdk.test.lib.jfr.Events;
/**
@@ -57,7 +58,9 @@ public static void main(String[] args) throws Throwable {
File tmp = Utils.createTempFile("TestDisabledEvents", ".tmp").toFile();
try (Recording recording = new Recording()) {
recording.disable(IOEvent.EVENT_FILE_READ);
- recording.disable(IOEvent.EVENT_FILE_WRITE);
+ recording.disable(IOEvent.EVENT_FILE_WRITE);
+ recording.disable(EventNames.FileReadIOStatistics);
+ recording.disable(EventNames.FileWriteIOStatistics);
recording.start();
useRandomAccessFile(tmp);
@@ -70,6 +73,8 @@ public static void main(String[] args) throws Throwable {
System.out.println("Got eventName:" + eventName);
assertNotEquals(eventName, IOEvent.EVENT_FILE_READ, "Got disabled read event");
assertNotEquals(eventName, IOEvent.EVENT_FILE_WRITE, "Got disabled write event");
+ assertNotEquals(eventName, EventNames.FileReadIOStatistics, "Got disabled FileReadIOStatistics Event");
+ assertNotEquals(eventName, EventNames.FileWriteIOStatistics, "Got disabled FileWriteIOStatistics Event");
}
}
}
diff --git a/test/jdk/jdk/jfr/event/io/TestFileChannelEvents.java b/test/jdk/jdk/jfr/event/io/TestFileChannelEvents.java
index 11ae0a12e4fb5..dc0114543a47e 100644
--- a/test/jdk/jdk/jfr/event/io/TestFileChannelEvents.java
+++ b/test/jdk/jdk/jfr/event/io/TestFileChannelEvents.java
@@ -36,6 +36,7 @@
import jdk.jfr.Recording;
import jdk.jfr.consumer.RecordedEvent;
import jdk.test.lib.Utils;
+import jdk.test.lib.jfr.EventNames;
import jdk.test.lib.jfr.Events;
/**
@@ -54,6 +55,8 @@ public static void main(String[] args) throws Throwable {
recording.enable(IOEvent.EVENT_FILE_FORCE).withThreshold(Duration.ofMillis(0));
recording.enable(IOEvent.EVENT_FILE_READ).withThreshold(Duration.ofMillis(0));
recording.enable(IOEvent.EVENT_FILE_WRITE).withThreshold(Duration.ofMillis(0));
+ recording.enable(EventNames.FileReadIOStatistics);
+ recording.enable(EventNames.FileWriteIOStatistics);
recording.start();
ByteBuffer bufA = ByteBuffer.allocateDirect(10);
@@ -115,6 +118,8 @@ public static void main(String[] args) throws Throwable {
recording.stop();
List events = Events.fromRecording(recording);
IOHelper.verifyEqualsInOrder(events, expectedEvents);
+ Events.hasEvent(events, EventNames.FileReadIOStatistics);
+ Events.hasEvent(events, EventNames.FileWriteIOStatistics);
}
}
}
diff --git a/test/jdk/jdk/jfr/event/io/TestFileIOStatisticsEvents.java b/test/jdk/jdk/jfr/event/io/TestFileIOStatisticsEvents.java
new file mode 100644
index 0000000000000..afcb779e7758e
--- /dev/null
+++ b/test/jdk/jdk/jfr/event/io/TestFileIOStatisticsEvents.java
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.jfr.event.io;
+
+import static jdk.test.lib.Asserts.assertEquals;
+import static jdk.test.lib.Asserts.assertNotEquals;
+import static jdk.test.lib.Asserts.assertGreaterThanOrEqual;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.RandomAccessFile;
+import java.nio.ByteBuffer;
+import java.nio.channels.FileChannel;
+import java.time.Duration;
+import java.util.List;
+import jdk.jfr.Recording;
+import jdk.jfr.consumer.RecordedEvent;
+import jdk.test.lib.jfr.EventNames;
+import jdk.test.lib.jfr.Events;
+import jdk.test.lib.Utils;
+
+/**
+ * @test
+ * @key jfr
+ * @requires vm.hasJFR
+ * @library /test/lib /test/jdk
+ * @run main/othervm jdk.jfr.event.io.TestFileIOStatisticsEvents
+ */
+public class TestFileIOStatisticsEvents {
+ private static final int writeInt = 'A';
+ private static final byte[] writeBuf = { 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
+ 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' };
+ private static int accWriteExpected = 0;
+ private static int accReadExpected = 0;
+ public static void main(String[] args) throws Throwable {
+ Recording recording = new Recording();
+ File tmp = Utils.createTempFile("TestFileIOStatistics", ".tmp").toFile();
+ recording.enable(EventNames.FileReadIOStatistics);
+ recording.enable(EventNames.FileWriteIOStatistics);
+
+ recording.start();
+ useFileChannel(tmp);
+ useRandomAccessFile(tmp);
+ useFileStream(tmp);
+ recording.stop();
+
+ checkForDisabledFileEvents(recording);
+ checkForEnabledFileIOStatistics(recording);
+ }
+
+ private static void useFileChannel(File tmp) throws Throwable {
+ tmp.delete();
+ try (RandomAccessFile rf = new RandomAccessFile(tmp, "rw"); FileChannel ch = rf.getChannel()) {
+ final String bufContent = "0123456789";
+ final int bufSize = bufContent.length();
+ ByteBuffer writeBuf = ByteBuffer.allocateDirect(bufSize);
+ writeBuf.put(bufContent.getBytes());
+ writeBuf.flip();
+ int writeSize = ch.write(writeBuf);
+ accWriteExpected = accWriteExpected + writeSize;
+
+ ch.position(0);
+ ByteBuffer readBuf = ByteBuffer.allocateDirect(bufSize);
+ int readSize = ch.read(readBuf);
+ accReadExpected = accReadExpected + readSize;
+ assertEquals(accWriteExpected, accReadExpected, "Total Read bytes != Total write bytes in the useFileChannel");
+ }
+ }
+
+ private static void useRandomAccessFile(File tmp) throws Throwable {
+ tmp.delete();
+ try (RandomAccessFile ras = new RandomAccessFile(tmp, "rw")) {
+ ras.write(writeInt);
+ ras.write(writeBuf);
+ ras.seek(0);
+ accWriteExpected = accWriteExpected + writeBuf.length + 1;
+ int readInt = ras.read();
+ byte[] readBuf = new byte[writeBuf.length];
+ int readSize = ras.read(readBuf);
+ accReadExpected = accReadExpected + readSize + 1;
+ // Try to read more which should generate EOF.
+ readInt = ras.read();
+ assertEquals(readInt, -1, "Wrong readInt after EOF");
+ }
+ assertEquals(accWriteExpected, accReadExpected, "Total Read bytes != Total write bytes in the RandomAccessFile");
+ }
+
+ private static void useFileStream(File tmp) throws Throwable {
+ tmp.delete();
+ try (FileOutputStream fos = new FileOutputStream(tmp)) {
+ fos.write(writeInt);
+ fos.write(writeBuf);
+ accWriteExpected = accWriteExpected + writeBuf.length + 1;
+ }
+ try(FileInputStream fis = new FileInputStream(tmp)){
+ int readInt = fis.read();
+ byte[] readBuf = new byte[writeBuf.length];
+ int readSize = fis.read(readBuf);
+ accReadExpected = accReadExpected + readSize + 1;
+ readInt = fis.read();
+ assertEquals(readInt, -1, "Wrong readInt after EOF");
+ }
+ assertEquals(accWriteExpected, accReadExpected, "Total Read bytes != Total write bytes in the FileStream");
+
+ }
+
+ private static void checkForDisabledFileEvents(Recording recording) throws Throwable {
+ for (RecordedEvent event : Events.fromRecording(recording)) {
+ final String eventName = event.getEventType().getName();
+ System.out.println("Got eventName:" + eventName);
+ assertNotEquals(eventName, IOEvent.EVENT_FILE_READ, "Got disabled read event");
+ assertNotEquals(eventName, IOEvent.EVENT_FILE_WRITE, "Got disabled write event");
+ assertNotEquals(eventName, IOEvent.EVENT_FILE_FORCE, "Got disabled force event");
+ }
+ }
+
+ private static void checkForEnabledFileIOStatistics(Recording recording) throws Throwable {
+ boolean hasNonZeroReadRate = false;
+ boolean hasNonZeroWriteRate = false;
+ String accWrite = null;
+ String accRead = null;
+
+ //JFR EventAttributes
+ final String WRITE_RATE = "writeRate";
+ final String ACC_WRITE_BYTES = "accWrite";
+ final String READ_RATE = "readRate";
+ final String ACC_READ_BYTES = "accRead";
+
+ List events = Events.fromRecording(recording);
+
+ Events.hasEvents(events);
+ Events.hasEvent(events, EventNames.FileReadIOStatistics);
+ Events.hasEvent(events, EventNames.FileWriteIOStatistics);
+
+ for (RecordedEvent event : events) {
+ if (event.getEventType().getName().toString().equals(EventNames.FileWriteIOStatistics)) {
+ String writeRateVal = Events.assertField(event, WRITE_RATE).getValue().toString();
+ accWrite = Events.assertField(event, ACC_WRITE_BYTES).getValue().toString();
+ if (Double.parseDouble(writeRateVal) > 0) {
+ hasNonZeroWriteRate = true;
+ }
+ } else if (event.getEventType().getName().toString().equals(EventNames.FileReadIOStatistics)) {
+ String readRateVal = Events.assertField(event, READ_RATE).getValue().toString();
+ accRead = Events.assertField(event, ACC_READ_BYTES).getValue().toString();
+ if (Double.parseDouble(readRateVal) > 0) {
+ hasNonZeroReadRate = true;
+ }
+ }
+ }
+ assertEquals(hasNonZeroWriteRate, true);
+ assertEquals(hasNonZeroReadRate, true);
+
+ assertGreaterThanOrEqual(Integer.parseInt(accRead), accReadExpected, "The accumulated read bytes:" + accRead + " should be equal to expected Read Bytes:" + accReadExpected);
+ assertGreaterThanOrEqual(Integer.parseInt(accWrite), accWriteExpected,
+ "The accumulated write bytes:" + accWrite + " should be equal or more that expected length:" + accWriteExpected);
+ }
+}
\ No newline at end of file
diff --git a/test/jdk/jdk/jfr/event/io/TestFileStreamEvents.java b/test/jdk/jdk/jfr/event/io/TestFileStreamEvents.java
index d557a8dfd7de2..1e11f44acb7e8 100644
--- a/test/jdk/jdk/jfr/event/io/TestFileStreamEvents.java
+++ b/test/jdk/jdk/jfr/event/io/TestFileStreamEvents.java
@@ -36,6 +36,7 @@
import jdk.jfr.consumer.RecordedEvent;
import jdk.test.lib.Utils;
import jdk.test.lib.jfr.Events;
+import jdk.test.lib.jfr.EventNames;
/**
* @test TestFileStreamEvents
@@ -53,6 +54,8 @@ public static void main(String[] args) throws Throwable {
try(FileOutputStream fos = new FileOutputStream(tmp); FileInputStream fis = new FileInputStream(tmp);) {
recording.enable(IOEvent.EVENT_FILE_READ).withThreshold(Duration.ofMillis(0));
recording.enable(IOEvent.EVENT_FILE_WRITE).withThreshold(Duration.ofMillis(0));
+ recording.enable(EventNames.FileReadIOStatistics);
+ recording.enable(EventNames.FileWriteIOStatistics);
recording.start();
int writeByte = 47;
@@ -88,6 +91,8 @@ public static void main(String[] args) throws Throwable {
recording.stop();
List events = Events.fromRecording(recording);
IOHelper.verifyEqualsInOrder(events, expectedEvents);
+ Events.hasEvent(events, EventNames.FileReadIOStatistics);
+ Events.hasEvent(events, EventNames.FileWriteIOStatistics);
}
}
}
diff --git a/test/jdk/jdk/jfr/event/io/TestRandomAccessFileEvents.java b/test/jdk/jdk/jfr/event/io/TestRandomAccessFileEvents.java
index 47fbc62d08d20..cf968bf22ab67 100644
--- a/test/jdk/jdk/jfr/event/io/TestRandomAccessFileEvents.java
+++ b/test/jdk/jdk/jfr/event/io/TestRandomAccessFileEvents.java
@@ -35,6 +35,7 @@
import jdk.jfr.consumer.RecordedEvent;
import jdk.test.lib.Utils;
import jdk.test.lib.jfr.Events;
+import jdk.test.lib.jfr.EventNames;
/**
* @test
@@ -52,6 +53,8 @@ public static void main(String[] args) throws Throwable {
recording.enable(IOEvent.EVENT_FILE_WRITE).withThreshold(Duration.ofMillis(0));
recording.enable(IOEvent.EVENT_FILE_READ).withThreshold(Duration.ofMillis(0));
+ recording.enable(EventNames.FileReadIOStatistics);
+ recording.enable(EventNames.FileWriteIOStatistics);
recording.start();
RandomAccessFile ras = new RandomAccessFile(tmp, "rw");
@@ -103,6 +106,8 @@ public static void main(String[] args) throws Throwable {
recording.stop();
List events = Events.fromRecording(recording);
IOHelper.verifyEqualsInOrder(events, expectedEvents);
+ Events.hasEvent(events, EventNames.FileReadIOStatistics);
+ Events.hasEvent(events, EventNames.FileWriteIOStatistics);
}
}
diff --git a/test/lib/jdk/test/lib/jfr/EventNames.java b/test/lib/jdk/test/lib/jfr/EventNames.java
index fd0dcc6895aab..96ac1758d7009 100644
--- a/test/lib/jdk/test/lib/jfr/EventNames.java
+++ b/test/lib/jdk/test/lib/jfr/EventNames.java
@@ -192,6 +192,8 @@ public class EventNames {
public static final String FileForce = PREFIX + "FileForce";
public static final String FileRead = PREFIX + "FileRead";
public static final String FileWrite = PREFIX + "FileWrite";
+ public static final String FileWriteIOStatistics = PREFIX + "FileWriteIOStatistics";
+ public static final String FileReadIOStatistics = PREFIX + "FileReadIOStatistics";
public static final String SocketRead = PREFIX + "SocketRead";
public static final String SocketWrite = PREFIX + "SocketWrite";
public static final String ExceptionStatistics = PREFIX + "ExceptionStatistics";