-
Bug
-
Resolution: Unresolved
-
P3
-
11, 15
-
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
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
- relates to
-
JDK-8258036 Significant performance regression in File.getCanonicalFile, getCanonicalPath
-
- Closed
-