Java文件I / O性能随时间减less

我正尝试使用Java 5.0 x64(在Windows XP上)对大文件(〜4GB)进行一次性读取。

最初文件读取速度非常快,但是吞吐量逐渐下降,而且随着时间的推移,我的机器似乎很没有响应。

我使用ProcessExplorer来监视文件I / O统计,看起来最初的读取速度为500MB / sec,但是这个速度逐渐下降到20MB / sec左右。

关于维护File I / O率的最佳方法,特别是使用Java读取大文件的想法?

以下是一些显示“间隔时间”不断增加的testing代码。 只需传递一个至less500MB的文件即可。

import java.io.File; import java.io.RandomAccessFile; public class MultiFileReader { public static void main(String[] args) throws Exception { MultiFileReader mfr = new MultiFileReader(); mfr.go(new File(args[0])); } public void go(final File file) throws Exception { RandomAccessFile raf = new RandomAccessFile(file, "r"); long fileLength = raf.length(); System.out.println("fileLen: " + fileLength); raf.close(); long startTime = System.currentTimeMillis(); doChunk(0, file, 0, fileLength); System.out.println((System.currentTimeMillis() - startTime) + " ms"); } public void doChunk(int threadNum, File file, long start, long end) throws Exception { System.out.println("Starting partition " + start + " to " + end); RandomAccessFile raf = new RandomAccessFile(file, "r"); raf.seek(start); long cur = start; byte buf[] = new byte[1000]; int lastPercentPrinted = 0; long intervalStartTime = System.currentTimeMillis(); while (true) { int numRead = raf.read(buf); if (numRead == -1) { break; } cur += numRead; if (cur >= end) { break; } int percentDone = (int)(100.0 * (cur - start) / (end - start)); if (percentDone % 5 == 0) { if (lastPercentPrinted != percentDone) { lastPercentPrinted = percentDone; System.out.println("Thread" + threadNum + " Percent done: " + percentDone + " Interval time: " + (System.currentTimeMillis() - intervalStartTime)); intervalStartTime = System.currentTimeMillis(); } } } raf.close(); } } 

谢谢!

我非常怀疑你真的从你的磁盘获得500MB每秒。 数据有可能被操作系统缓存 – 而每秒20MB的数据就是它真正碰到磁盘时发生的情况。

这将很可能在Vista资源管理器的磁盘部分可见 – 而低技术的方式告诉是听磁盘驱动器:)

根据您的具体硬件以及发生了什么事情,您可能需要合理地努力工作,速度超过20MB /秒。

我想也许你并没有真正达到500MB /秒的规模。

你希望做什么,并且你有没有检查你的具体驱动器甚至在理论上是可行的?

Java垃圾收集器可能是这里的一个瓶颈。

我会使缓冲区更大和私人的类,所以它被重用,而不是每次调用doChunk()分配。

 public class MultiFileReader { private byte buf[] = new byte[256*1024]; ... } 

您可以使用JConsole监视您的应用程序,包括内存使用情况。 500 MB /秒听起来很不错。

有关实现和VM参数的更多信息将有所帮助。

检查静态无效read3()抛出IOException {

  // read from the file with buffering // and with direct access to the buffer MyTimer mt = new MyTimer(); FileInputStream fis = new FileInputStream(TESTFILE); cnt3 = 0; final int BUFSIZE = 1024; byte buf[] = new byte[BUFSIZE]; int len; while ((len = fis.read(buf)) != -1) { for (int i = 0; i < len; i++) { if (buf[i] == 'A') { cnt3++; } } } fis.close(); System.out.println("read3 time = " + mt.getElapsed()); } 

来自http://java.sun.com/developer/JDCTechTips/2002/tt0305.html

最佳缓冲区大小可能取决于操作系统。 你的也许是小的。