Java File.createNewFile()比FileOutputStream慢得多
在使用File.createNewFile()或File.createTempFile()时,我观察到一个有趣的性能下降。下面的代码创建48个线程,每个线程将大约128MB的数据写入不同的文件。如果我按原样运行代码,在我的特定机器上大约需要60秒。如果我完全按照原样运行代码,除了注释掉f.createTempFile()调用,那么大约需要5秒钟Java File.createNewFile()比FileOutputStream慢得多,java,Java,在使用File.createNewFile()或File.createTempFile()时,我观察到一个有趣的性能下降。下面的代码创建48个线程,每个线程将大约128MB的数据写入不同的文件。如果我按原样运行代码,在我的特定机器上大约需要60秒。如果我完全按照原样运行代码,除了注释掉f.createTempFile()调用,那么大约需要5秒钟 import java.util.*; import java.util.concurrent.*; import java.io.File; impo
import java.util.*;
import java.util.concurrent.*;
import java.io.File;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public final class TestFile implements Runnable {
public void run() {
byte[] b = new byte[128205100];
Arrays.fill(b, (byte)10);
try {
File f = new File("/tmp/test", UUID.randomUUID().toString());
// If I comment the following f.createNewFile() then the code takes
// 5 seconds rather than 60 to execute.
f.createNewFile();
FileOutputStream fOutputStream = new FileOutputStream(f);
BufferedOutputStream fBufStream = new BufferedOutputStream(fOutputStream, 32768);
fBufStream.write(b);
fBufStream.close();
} catch (IOException e) {
System.err.println("Caught IOException: " + e.getMessage());
}
}
public static void main(String[] args) {
final ExecutorService executorPool = Executors.newFixedThreadPool(48);
for (int counter=0; counter < 48; counter++) {
executorPool.execute(new TestFile());
}
try {
executorPool.shutdown();
executorPool.awaitTermination(120, TimeUnit.SECONDS);
} catch (InterruptedException e) {
System.err.println("Caught InterruptedException: " + e.getMessage());
}
}
}
import java.util.*;
导入java.util.concurrent.*;
导入java.io.File;
导入java.io.BufferedOutputStream;
导入java.io.FileOutputStream;
导入java.io.IOException;
公共final类TestFile实现Runnable{
公开募捐{
字节[]b=新字节[128205100];
数组。填充(b,(字节)10);
试一试{
文件f=新文件(“/tmp/test”,UUID.randomUUID().toString());
//如果我对以下f.createNewFile()进行注释,那么代码将
//执行时间为5秒,而不是60秒。
f、 createNewFile();
FileOutputStream fOutputStream=新的FileOutputStream(f);
BufferedOutputStream fBufStream=新的BufferedOutputStream(fOutputStream,32768);
fBufStream.write(b);
fBufStream.close();
}捕获(IOE异常){
System.err.println(“捕获的IOException:+e.getMessage());
}
}
公共静态void main(字符串[]args){
final ExecutorService executorPool=Executors.newFixedThreadPool(48);
用于(int计数器=0;计数器<48;计数器++){
executorPool.execute(新的TestFile());
}
试一试{
executorPool.shutdown();
执行器池。等待终止(120,时间单位。秒);
}捕捉(中断异常e){
System.err.println(“捕获的中断异常:+e.getMessage());
}
}
}
通过使用jstack,我可以看到,在运行上述代码时,所有线程的大部分时间都花在close0()上。不幸的是,此函数是本机函数:-/知道它的源代码在哪里吗
"Thread-47" #68 prio=5 os_prio=0 tid=0x00007f21001de800 nid=0x4eb4 runnable [0x00007f209edec000]
java.lang.Thread.State: RUNNABLE
at java.io.FileOutputStream.close0(Native Method)
at java.io.FileOutputStream.access$000(FileOutputStream.java:53)
at java.io.FileOutputStream$1.close(FileOutputStream.java:356)
at java.io.FileDescriptor.closeAll(FileDescriptor.java:212)
- locked <0x00000005908ad628> (a java.io.FileDescriptor)
at java.io.FileOutputStream.close(FileOutputStream.java:354)
at java.io.FilterOutputStream.close(FilterOutputStream.java:159)
at TestFile.run(TestFile.java:19)
at java.lang.Thread.run(Thread.java:745)
“Thread-47”#68优先级=5 os_优先级=0 tid=0x00007f21001de800 nid=0x4eb4可运行[0x00007f209edec000]
java.lang.Thread.State:可运行
位于java.io.FileOutputStream.close0(本机方法)
在java.io.FileOutputStream.access$000(FileOutputStream.java:53)
位于java.io.FileOutputStream$1.close(FileOutputStream.java:356)
位于java.io.FileDescriptor.closeAll(FileDescriptor.java:212)
-锁定(java.io.FileDescriptor)
在java.io.FileOutputStream.close(FileOutputStream.java:354)处
在java.io.FilterOutputStream.close(FilterOutputStream.java:159)处
运行(TestFile.java:19)
运行(Thread.java:745)
我猜某个地方(在本地close0?)有人在发出同步,但我找不到。我已经在一些机器上测试过了,在其中一些机器上我看不到性能下降。因此,这可能是基于配置或环境的
我使用Java8在Ubuntu上运行
任何帮助都将不胜感激。谢谢 这很简单
File.createNewFile()
按该名称搜索一个文件,如果该文件不存在,则创建一个新文件;如果失败,则创建一个新文件,您可以正确忽略该文件,因为成功与否无关紧要newfileoutputstream()
以相同的名称搜索任何现有文件,将其删除,然后创建一个新文件
因此,很明显,File.createNewFile()
后面跟着newfileoutputstream()
,这完全是浪费时间,因为它迫使操作系统:
解决方案:在
newfileoutputstream(…)
之前不要调用File.createNewFile()
。或者新建FileWriter(…)
,或者新建PrintStream/PrintWriter(…)
。没有什么可以获得,时间和空间可以浪费。这很简单File.createNewFile()
按该名称搜索一个文件,如果该文件不存在,则创建一个新文件;如果失败,则创建一个新文件,您可以正确忽略该文件,因为成功与否无关紧要newfileoutputstream()
以相同的名称搜索任何现有文件,将其删除,然后创建一个新文件
因此,很明显,File.createNewFile()
后面跟着newfileoutputstream()
,这完全是浪费时间,因为它迫使操作系统:
解决方案:在
newfileoutputstream(…)
之前不要调用File.createNewFile()
。或者新建FileWriter(…)
,或者新建PrintStream/PrintWriter(…)
。没有什么可以获得,时间和空间可以浪费。我不能说它为什么会慢那么多,但是,它从文件
参数中使用的只是它的名称和对路径有效性的检查:如果文件已经存在,它会覆盖该文件。因此,没有必要先创建它。同意Turner的观点,createnewfile会检查系统的securityManager,其中作为FileOutputStream只是简单地尝试写入。这不是文件权限问题,因为文件是以相同的权限(rw)创建的。这也不是数据仍然需要刷新的情况,因为如果在fStream.close()之前添加fStream.flush(),会得到相同的行为。谢谢@AndyTurner和nafas。我不认为是安全经理,因为FileO