簡體   English   中英

Java文件I / O性能隨着時間的推移而減少

[英]Java File I/O Performance Decreases Over Time

我正在嘗試使用Java 5.0 x64(在Windows XP上)執行大文件(~4GB)的一次性讀取。

最初文件讀取速度非常快,但逐漸吞吐量大幅減慢,隨着時間的推移,我的機器似乎反應遲鈍。

我已經使用ProcessExplorer監視文件I / O統計信息,看起來該進程最初讀取500MB /秒,但這個速率逐漸降低到大約20MB /秒。

關於維護文件I / O速率的最佳方法的任何想法,特別是使用Java讀取大文件?

這是一些測試代碼,顯示“間隔時間”繼續增加。 只需傳遞一個至少500MB的文件。

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參數的更多信息將會有所幫助。

檢查static void 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

最佳緩沖區大小可能取決於操作系統。 你的可能很小。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM