Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8258196

File operations 3 to 4 times slower in Java 15.1 than in Java 8 on Windows

XMLWordPrintable

    • x86_64
    • windows_10

      ADDITIONAL SYSTEM INFORMATION :
      Windows 10

      A DESCRIPTION OF THE PROBLEM :
      On Windows 10 operations which copy files and read them are 3-4 slower when performed with Java 15.1 than when performed with Java 1.8.
      On Mac OSX I cannot reproduce the slow down.
      I'm testing the code using the folder which can be downloaded from here: https://github.com/oxygenxml/userguide/tree/master/DITA
      The folder contains about 6000 small files (XML files and images).

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      I'm attaching a piece of code which goes through a folder with lots of files (6000), copies each files to the temporary files folder and reads content from it.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Run with Java 15 the code should take as long as when it's run with Java 1.8
      ACTUAL -
      With Java 1.8 the code finishes in about 11 seconds. With Java 15 it needs 40 seconds to run.

      ---------- BEGIN SOURCE ----------
      public class ABC {
        static byte[] bytes = new byte[8 * 1024];
        static int cnt = 0;
        
          /**
           * Copies srcFile to dstFile.
           *
           * @param srcFile The source File.
           * @param dstFile The destination File.
           * @param ignoreFileFlags If <code>true</code> the flags should not be transmitted to
           * the copied file. (executable, readable, writable).
           * @throws IOException Thrown if file copy fails.
           */
          private static void copyFile(File srcFile, File dstFile, boolean ignoreFileFlags) throws IOException {
            File parentFolder = dstFile.getParentFile();
            if (!parentFolder.exists()) {
              if (!parentFolder.mkdirs()) {
                throw new IOException("Could not create folder: " + parentFolder);
              }
            }
        
            FileInputStream fis = new FileInputStream(srcFile);
            try {
              FileOutputStream fos = new FileOutputStream(dstFile);
              copyInputStreamToOutputStream(fis, fos, true);
            } finally {
              /*
               * Streams are always closed by the "copy" method.
               * But if the output stream cannot not be created, make sure the input stream is closed safely and silently.
               */
              fis.close();
            }
            
            try {
              long srcLastModified = srcFile.lastModified();
              if(srcLastModified > 0) {
                dstFile.setLastModified(srcLastModified);
              }
              if (!ignoreFileFlags) {
                if (!srcFile.canWrite()) {
                  //Set the read-only property
                  dstFile.setReadOnly();
                }
                dstFile.setExecutable(srcFile.canExecute());
                dstFile.setReadable(srcFile.canRead());
                dstFile.setWritable(srcFile.canWrite());
              }
            } catch (SecurityException e) {
              e.printStackTrace();
            }
          }
        
        private static void read(File file) {
          try {
            File dst = File.createTempFile("test", ".xml");
            dst.deleteOnExit();
            copyFile(file, dst, false);
            System.err.println(file);
            FileInputStream fis = new FileInputStream(dst);
            int len = -1;
            while((len = fis.read(bytes)) != -1) {
              for (int i = 0; i < len; i++) {
                if(bytes[i] == 0) {
                  cnt ++;
                }
              }
            };
            fis.close();
            dst.delete();
          } catch (FileNotFoundException e) {
            e.printStackTrace();
          } catch (IOException e) {
            e.printStackTrace();
          }
        }
        
          /**
         * Copies input stream content to output stream.
         *
         * @param is The input stream.
         * @param os The output stream.
         * @param closeOutputStream <code>true</code> to also close the output stream.
         * The input stream is always closed.
         *
         * @throws IOException Thrown if file copy fails.
         */
        public static void copyInputStreamToOutputStream(
            InputStream is, OutputStream os, boolean closeOutputStream) throws IOException {
          BufferedOutputStream bos = new BufferedOutputStream(os, 8000);
          BufferedInputStream bis = new BufferedInputStream(is, 8000);
          try {
            byte[] buff = new byte[8192 * 2];
            int count;
            while ((count = bis.read(buff)) != -1) {
              bos.write(buff, 0, count);
            }
          } finally {
            try {
              bis.close();
            } finally {
              if (closeOutputStream) {
                bos.close();
              } else {
                bos.flush();
              }
            }
          }
        }

        public static void main(String[] args) {
          File start = new File("D:\\git-projects\\userguide-private\\DITA");
          long before = System.currentTimeMillis();
          recurseRead(start);
          long after = System.currentTimeMillis();
          System.err.println("Took: " + (after - before));
          System.err.println(cnt);
        }

        private static void recurseRead(File file) {
          if(file.isDirectory()) {
            File[] files = file.listFiles();
            if(files != null) {
              for (int i = 0; i < files.length; i++) {
                recurseRead(files[i]);
              }
            }
          } else {
            read(file);
          }
        }
      }

      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      No workaround so far.

      FREQUENCY : always


        1. Test.java
          4 kB
          Anupam Dev

            bpb Brian Burkhalter
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            7 Start watching this issue

              Created:
              Updated: