【发布时间】:2014-05-22 03:24:56
【问题描述】:
我正在将大量字符串写入文件,并注意到在某些时候,写入操作开始需要比以前更多的时间来执行。大多数字符串都是唯一的,并且是在运行时使用StringBuilder 生成的,所以我认为这是问题所在,但事实证明还有其他原因。
我写了一个快速程序来看看发生了什么
public static void main(String[] args) {
long time, t1, t2;
int n = 10000;
int threshold = 10;
try {
BufferedWriter out = new BufferedWriter(new FileWriter("C:\\temp\\out.txt"));
for (int i = 0; i < n;i++) {
t1 = System.currentTimeMillis();
out.write("test\r\n"));
t2 = System.currentTimeMillis();
time = t2 - t1;
if (time > threshold) {
System.out.println(time);
}
}
out.close();
} catch(Exception e) {
e.printStackTrace();
}
}
我设置了一个阈值来过滤掉需要最少时间的写入操作。我将其设置为 10 毫秒。
当n = 10 000 时,我没有打印任何内容,这意味着写入速度很快。当我将n 增加到100 000、1 000 000、10 000 000 时,会打印出几个数字。然后在100 000 000,我开始看到很多数字被打印出来。将其增加到1 000 000 000,很多写操作需要几十到几百毫秒,这大大降低了吞吐量。
像我使用旋转磁盘驱动器或磁盘碎片时发生这种情况的原因可能有很多。我尝试将缓冲区大小增加到 1 MB 或 10 MB,但似乎没有帮助(实际上它似乎让事情变得更糟)。
我可以做些什么来避免这种超时吞吐量突然下降?
【问题讨论】:
-
使用
StringBuffer或StringBuilder? -
我不认为记录耗时超过 10 毫秒的单个写入操作的数量是衡量吞吐量的好方法,尤其是在涉及缓冲的情况下。最好测量一段时间内的平均写入速度。
-
@Alex 你的意思是,由于缓冲,一些写入根本不需要时间,因为它只是写入内存,而其他写入则需要更多时间,因为缓冲区已满并且需要刷新到磁盘?
-
是的,完全正确。看看 BufferedWriter 源代码。
-
会尝试这些建议stackoverflow.com/questions/1605332/…,但后来我用 UTF-8 编写,所以二进制写入可能会导致问题。
标签: java performance file-io