我在Eclipse中编写了一个java程序,它将3000万行写入文件。
第一次运行此代码时,写入文本文件(foo.txt)所花费的时间大约需要104秒。
我删除了我写过行的文本文件(foo.txt),然后再次运行程序。这次需要61秒。
我继续这个过程,每次运行程序时写入文件所花费的时间都在减少。写入文件的记录时间如下:
(以秒为单位,近似值)
104-> 61-> 39-> 25-> 18-> 16-> 16-> 16-> ...
我观察到的是,写入文本文件(foo.txt)所花费的时间一直在减少,直到它在16秒左右变得恒定。
我的java代码如下:
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.List;
public class fileWrite {
private static int file_sz = 30000000;
private static final String line = "Help I am a chinese guy trapped in a fortune cookie factory!!";
/*
No offense meant to any Chinese person, i apologise in advance if i have hurt your feelings.
*/
private static void write(List<String> list, Writer writer)throws IOException {
long start = System.currentTimeMillis();
for(String list_el: list){
writer.write(list_el);
}
writer.flush();
writer.close();
long end = System.currentTimeMillis();
System.out.println((end-start)/1000f + "seconds");
}
public static void main(String[] args) {
try{
File file = new File("foo.txt");
if(!file.exists()){
file.createNewFile();
}
FileWriter writer = new FileWriter(file.getAbsolutePath());
List<String> records = new ArrayList<String>(file_sz);
for(int i = 0;i<file_sz;++i){
records.add(line);
}
write(records,writer);
}
catch(Exception ex){
ex.printStackTrace();
}
}
}
我想问的问题是:
为什么写入文件所需的时间变得不变? 时间减少是否与缓存有关?
如果有人能够了解幕后发生的事情,我将非常感激。任何能够详细解释系统工作的链接也会受到欢迎。
提前谢谢。
答案 0 :(得分:2)
这可能是您的操作系统,特别是您的文件系统正在完成其工作。
文件系统将文件表示为一系列块或范围;这样,文件就不必一直适合您的存储介质。
第一次编写文件时,文件系统以它可以找到的第一个空闲块开始,写入时,获得下一个空闲文件,将其添加到文件中的块列表中,依此类推
随着文件的增长,文件系统放弃了在其他块之间查找块,但在介质上获得了连续的可用空间块,并且始终将下一个块附加到文件中。这既降低了文件系统开销,又降低了硬盘驱动器的开销,减少了由于写标头缓慢进入新位置而导致的延迟。
现在,删除原始文件后,文件系统内部指针指向&#34;第一个空闲块&#34;可能仍然在连续的自由空间区域。
此外,现代操作系统可能很聪明,并且了解您的程序始终在特定文件夹中打开一个文件以进行访问,并在其中放入大量数据,因此可能会优化文件系统的工作方式。
最可能发生的事情是Java和你的操作系统都在RAM中有写缓存,它存储在实际写入磁盘之前/之前写入文件的数据。这些缓存是有弹性的;当您编写大量数据时,操作系统会占用更多空闲RAM用于写入缓存(例如,远离读取缓存)。程序完成后,不再需要写入缓存 - 但由于它没有以任何其他方式使用,下次编写大文件时,操作系统可以非常快速地将该内存分配给写入缓存