首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Java 讀取 Level-1 行情 DBF 文件極致優化(二):NIO 讀取與緩存複用

     編輯:Java 綜合教學

Java 讀取 Level-1 行情 DBF 文件極致優化(二)

承接上文,繼續介紹優化三、四。

優化三:採用 NIO 讀取文件

許多開源 DBF 庫基於流 I/O (InputStream),改用 NIO (RandomAccessFile + FileChannel + ByteBuffer) 可一次性將文件加載入內存。測試表明 NIO 比流方式快 ~5 倍。提供改進版 DBFReader (含後續優化) 下載:

DBFReader庫 DBFReader 庫下載

核心代碼片段:

// 建立 Channel
this.dbf = new RandomAccessFile(file, "r");
this.fc = dbf.getChannel();

// 加載指定片段到 DirectByteBuffer (內核緩存區,速度更快)
private ByteBuffer loadData(int offset, int length) throws IOException {
    ByteBuffer b = ByteBuffer.allocateDirect(length);
    fc.position(offset);
    fc.read(b);
    b.rewind();
    return b;
}

allocateDirect 創建 DirectBuffer,雖分銷毀較慢,但讀取更快,後續優化將解決分配開銷。

優化四:減少讀取時內存重複分配與 GC

原流程:整文件讀入 ByteBuffer → 每行新建 byte[] → 封裝 Record 對象。行情文件每幾秒刷新,格式固定,行大小不變,可複用緩存。

引入 CacheManager 管理可複用的 ByteBuffer 與 byte[] 列表:

public class CacheManager {
    private ByteBuffer byteBuffer; private int bufSize;
    private List<byte[]> byteArrayList; private int bytesSize;

    public ByteBuffer getByteBuffer(int size) {
        if (bufSize < size) {
            byteBuffer = ByteBuffer.allocateDirect(size + 8*1024); // 多分配避免擴容
            bufSize = size + 8*1024;
        }
        byteBuffer.clear();
        return byteBuffer;
    }
    public List<byte[]> getByteArrayList(int rowNum, int byteLength) {
        if (bytesSize != byteLength) { byteArrayList = new ArrayList<>(); bytesSize = byteLength; }
        if (byteArrayList.size() < rowNum) {
            int add = rowNum - byteArrayList.size() + 100;
            for (int i=0; i<add; i++) byteArrayList.add(new byte[bytesSize]);
        }
        return byteArrayList;
    }
}

改造讀取方法 recordsWithOutDel_efficiently:

public List<byte[]> recordsWithOutDel_efficiently(CacheManager cm) throws IOException {
    ByteBuffer bb = cm.getByteBuffer(getCount() * getRecordLength());
    fc.position(getDataIndex()); fc.read(bb); bb.rewind();
    List<byte[]> rds = new ArrayList<>(getCount());
    List<byte[]> bufList = cm.getByteArrayList(getCount(), getRecordLength());
    for (int i=0; i<getCount(); i++) {
        byte[] b = bufList.get(i);
        bb.get(b);
        if ((char)b[0] != '*') rds.add(b);
    }
    bb.clear();
    return rds; // 直接返回 byte[] 列表,避免 Record 對象創建
}

測試:緩存機制將讀取耗時從 ~5ms 降至 ~2ms,提升約 1 倍。下一步優化將針對字段解析與並行處理(見第三篇)。

原文:https://www.cnblogs.com/Binhua-Liu/p/5615299.html

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved