changeset 59277:ab5848d09175

8244936: Reduce JNI overhead of accessing FileDescriptor Reviewed-by: rriggs, alanb
author redestad
date Wed, 13 May 2020 22:25:14 +0200
parents 0312e36e1daf
children 26a4100f7102
files src/java.base/share/native/libjava/FileInputStream.c src/java.base/share/native/libjava/RandomAccessFile.c src/java.base/share/native/libjava/io_util.c src/java.base/unix/native/libjava/io_util_md.c src/java.base/unix/native/libjava/io_util_md.h src/java.base/windows/native/libjava/io_util_md.c src/java.base/windows/native/libjava/io_util_md.h test/micro/org/openjdk/bench/java/io/RandomAccessRead.java
diffstat 8 files changed, 66 insertions(+), 45 deletions(-) [+]
line wrap: on
line diff
--- a/src/java.base/share/native/libjava/FileInputStream.c	Wed May 13 20:19:09 2020 +0200
+++ b/src/java.base/share/native/libjava/FileInputStream.c	Wed May 13 22:25:14 2020 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2020, 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
@@ -76,7 +76,7 @@
 Java_java_io_FileInputStream_skip0(JNIEnv *env, jobject this, jlong toSkip) {
     jlong cur = jlong_zero;
     jlong end = jlong_zero;
-    FD fd = GET_FD(this, fis_fd);
+    FD fd = getFD(env, this, fis_fd);
     if (fd == -1) {
         JNU_ThrowIOException (env, "Stream Closed");
         return 0;
@@ -92,7 +92,7 @@
 JNIEXPORT jint JNICALL
 Java_java_io_FileInputStream_available0(JNIEnv *env, jobject this) {
     jlong ret;
-    FD fd = GET_FD(this, fis_fd);
+    FD fd = getFD(env, this, fis_fd);
     if (fd == -1) {
         JNU_ThrowIOException (env, "Stream Closed");
         return 0;
--- a/src/java.base/share/native/libjava/RandomAccessFile.c	Wed May 13 20:19:09 2020 +0200
+++ b/src/java.base/share/native/libjava/RandomAccessFile.c	Wed May 13 22:25:14 2020 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2020, 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
@@ -94,7 +94,7 @@
     FD fd;
     jlong ret;
 
-    fd = GET_FD(this, raf_fd);
+    fd = getFD(env, this, raf_fd);
     if (fd == -1) {
         JNU_ThrowIOException(env, "Stream Closed");
         return -1;
@@ -111,7 +111,7 @@
     FD fd;
     jlong length = jlong_zero;
 
-    fd = GET_FD(this, raf_fd);
+    fd = getFD(env, this, raf_fd);
     if (fd == -1) {
         JNU_ThrowIOException(env, "Stream Closed");
         return -1;
@@ -128,7 +128,7 @@
 
     FD fd;
 
-    fd = GET_FD(this, raf_fd);
+    fd = getFD(env, this, raf_fd);
     if (fd == -1) {
         JNU_ThrowIOException(env, "Stream Closed");
         return;
@@ -147,7 +147,7 @@
     FD fd;
     jlong cur;
 
-    fd = GET_FD(this, raf_fd);
+    fd = getFD(env, this, raf_fd);
     if (fd == -1) {
         JNU_ThrowIOException(env, "Stream Closed");
         return;
--- a/src/java.base/share/native/libjava/io_util.c	Wed May 13 20:19:09 2020 +0200
+++ b/src/java.base/share/native/libjava/io_util.c	Wed May 13 22:25:14 2020 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1994, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2020, 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
@@ -39,7 +39,7 @@
 readSingle(JNIEnv *env, jobject this, jfieldID fid) {
     jint nread;
     char ret;
-    FD fd = GET_FD(this, fid);
+    FD fd = getFD(env, this, fid);
     if (fd == -1) {
         JNU_ThrowIOException(env, "Stream Closed");
         return -1;
@@ -101,7 +101,7 @@
         buf = stackBuf;
     }
 
-    fd = GET_FD(this, fid);
+    fd = getFD(env, this, fid);
     if (fd == -1) {
         JNU_ThrowIOException(env, "Stream Closed");
         nread = -1;
@@ -127,7 +127,7 @@
     // Discard the 24 high-order bits of byte. See OutputStream#write(int)
     char c = (char) byte;
     jint n;
-    FD fd = GET_FD(this, fid);
+    FD fd = getFD(env, this, fid);
     if (fd == -1) {
         JNU_ThrowIOException(env, "Stream Closed");
         return;
@@ -178,7 +178,7 @@
     if (!(*env)->ExceptionOccurred(env)) {
         off = 0;
         while (len > 0) {
-            fd = GET_FD(this, fid);
+            fd = getFD(env, this, fid);
             if (fd == -1) {
                 JNU_ThrowIOException(env, "Stream Closed");
                 break;
--- a/src/java.base/unix/native/libjava/io_util_md.c	Wed May 13 20:19:09 2020 +0200
+++ b/src/java.base/unix/native/libjava/io_util_md.c	Wed May 13 22:25:14 2020 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2020, 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
@@ -92,6 +92,14 @@
     return fd;
 }
 
+FD getFD(JNIEnv *env, jobject obj, jfieldID fid) {
+  jobject fdo = (*env)->GetObjectField(env, obj, fid);
+  if (fdo == NULL) {
+    return -1;
+  }
+  return (*env)->GetIntField(env, fdo, IO_fd_fdID);
+}
+
 void
 fileOpen(JNIEnv *env, jobject this, jstring path, jfieldID fid, int flags)
 {
@@ -108,10 +116,10 @@
         if (fd != -1) {
             jobject fdobj;
             jboolean append;
-            SET_FD(this, fd, fid);
-
             fdobj = (*env)->GetObjectField(env, this, fid);
             if (fdobj != NULL) {
+                // Set FD
+                (*env)->SetIntField(env, fdobj, IO_fd_fdID, fd);
                 append = (flags & O_APPEND) == 0 ? JNI_FALSE : JNI_TRUE;
                 (*env)->SetBooleanField(env, fdobj, IO_append_fdID, append);
             }
--- a/src/java.base/unix/native/libjava/io_util_md.h	Wed May 13 20:19:09 2020 +0200
+++ b/src/java.base/unix/native/libjava/io_util_md.h	Wed May 13 22:25:14 2020 +0200
@@ -43,20 +43,12 @@
 FD handleOpen(const char *path, int oflag, int mode);
 
 /*
- * Macros to set/get fd from the java.io.FileDescriptor.  These
- * macros rely on having an appropriately defined 'this' object
- * within the scope in which they're used.
- * If GetObjectField returns null, SET_FD will stop and GET_FD
- * will simply return -1 to avoid crashing VM.
+ * Functions to get fd from the java.io.FileDescriptor field
+ * of an object.  These functions rely on having an appropriately
+ * defined object with a FileDescriptor object at the fid offset.
+ * If the FD object is null, return -1 to avoid crashing VM.
  */
-
-#define SET_FD(this, fd, fid) \
-    if ((*env)->GetObjectField(env, (this), (fid)) != NULL) \
-        (*env)->SetIntField(env, (*env)->GetObjectField(env, (this), (fid)),IO_fd_fdID, (fd))
-
-#define GET_FD(this, fid) \
-    (*env)->GetObjectField(env, (this), (fid)) == NULL ? \
-        -1 : (*env)->GetIntField(env, (*env)->GetObjectField(env, (this), (fid)), IO_fd_fdID)
+FD getFD(JNIEnv *env, jobject cur, jfieldID fid);
 
 /*
  * Macros to set/get fd when inside java.io.FileDescriptor
--- a/src/java.base/windows/native/libjava/io_util_md.c	Wed May 13 20:19:09 2020 +0200
+++ b/src/java.base/windows/native/libjava/io_util_md.c	Wed May 13 22:25:14 2020 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2020, 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
@@ -259,6 +259,14 @@
     return (jlong) h;
 }
 
+FD getFD(JNIEnv *env, jobject obj, jfieldID fid) {
+  jobject fdo = (*env)->GetObjectField(env, obj, fid);
+  if (fdo == NULL) {
+    return -1;
+  }
+  return (*env)->GetLongField(env, fdo, IO_handle_fdID);
+}
+
 void
 fileOpen(JNIEnv *env, jobject this, jstring path, jfieldID fid, int flags)
 {
@@ -266,10 +274,10 @@
     if (h >= 0) {
         jobject fdobj;
         jboolean append;
-        SET_FD(this, h, fid);
-
         fdobj = (*env)->GetObjectField(env, this, fid);
         if (fdobj != NULL) {
+            // Set FD
+            (*env)->SetLongField(env, fdobj, IO_handle_fdID, h);
             append = (flags & O_APPEND) == 0 ? JNI_FALSE : JNI_TRUE;
             (*env)->SetBooleanField(env, fdobj, IO_append_fdID, append);
         }
--- a/src/java.base/windows/native/libjava/io_util_md.h	Wed May 13 20:19:09 2020 +0200
+++ b/src/java.base/windows/native/libjava/io_util_md.h	Wed May 13 22:25:14 2020 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2020, 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
@@ -59,17 +59,12 @@
 FD winFileHandleOpen(JNIEnv *env, jstring path, int flags);
 
 /*
- * Macros to set/get fd from the java.io.FileDescriptor.
- * If GetObjectField returns null, SET_FD will stop and GET_FD
- * will simply return -1 to avoid crashing VM.
+ * Function to get fd from the java.io.FileDescriptor field of an
+ * object.  These functions rely on having an appropriately
+ * defined object with a FileDescriptor object at the fid offset.
+ * If the FD object is null, return -1 to avoid crashing VM.
  */
-#define SET_FD(this, fd, fid) \
-    if ((*env)->GetObjectField(env, (this), (fid)) != NULL) \
-        (*env)->SetLongField(env, (*env)->GetObjectField(env, (this), (fid)), IO_handle_fdID, (fd))
-
-#define GET_FD(this, fid) \
-    ((*env)->GetObjectField(env, (this), (fid)) == NULL) ? \
-      -1 : (*env)->GetLongField(env, (*env)->GetObjectField(env, (this), (fid)), IO_handle_fdID)
+FD getFD(JNIEnv *env, jobject cur, jfieldID fid);
 
 /*
  * Macros to set/get fd when inside java.io.FileDescriptor
--- a/test/micro/org/openjdk/bench/java/io/RandomAccessRead.java	Wed May 13 20:19:09 2020 +0200
+++ b/test/micro/org/openjdk/bench/java/io/RandomAccessRead.java	Wed May 13 22:25:14 2020 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2020, 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
@@ -51,11 +51,15 @@
     @Param("1000000")
     private int fileSize;
 
+    @Param("8192")
+    private int buffer;
+
     private RandomAccessFile raf;
     private long offset;
     private int deltaIndex;
     private int[] deltas;
     private File f;
+    private byte[] buf;
 
     @Setup(Level.Trial)
     public void beforeRun() throws IOException {
@@ -66,6 +70,7 @@
             }
         }
         deltas = new int[]{1, 2, 3, 5, 7, 11, 13, 17, 19, 23};
+        buf = new byte[buffer];
     }
 
     @TearDown(Level.Trial)
@@ -86,6 +91,20 @@
     }
 
     @Benchmark
+    public int testBuffer() throws IOException {
+        offset = offset + deltas[deltaIndex];
+        if (offset >= fileSize) {
+            offset = 0;
+        }
+        deltaIndex++;
+        if (deltaIndex >= deltas.length) {
+            deltaIndex = 0;
+        }
+        raf.seek(offset);
+        return raf.read(buf);
+    }
+
+    @Benchmark
     public int test() throws IOException {
         offset = offset + deltas[deltaIndex];
         if (offset >= fileSize) {
@@ -98,5 +117,4 @@
         raf.seek(offset);
         return raf.read();
     }
-
 }