简体   繁体   中英

RandomAccessFile is slow on first access

i am currently working with RandomAccessFile and come over a weird phenomenon. I am accessing a file that is 1.1TB big and only contains Bytes that are qual to 00000000.

I implemented the RandomAccessFile in the following way:

RandomAccessFile raf = new RandomAccessFile(new File("./db.bin"),"rw");

So my programm is generating a big list of Long values representing a BIT position and once it reached 1000 Entrys, it will flush the Data to a File:

    public void flush() {
       for( long l : lLongs ) {
           lseek = Long.divideUnsigned(l, 8L);
           raf.seek( lseek );
           byte b = raf.readByte();
           raf.seek( lseek );
           raf.writeByte( editByte(b,(int)l % 8) );
       }
       raf.close();
    }

    public byte editByte( byte b, int iBit ) {
      if( !isSet(b,iBit) ) {
        b = (byte)(b + Math.pow( 2, iBit));
      }
      return b;
    }

    boolean isSet(byte value, int bit){
       return (value >> bit & 1) == 1;
    }

Now i wonder why it takes so long? For 1000 Entrys it will take 15s in average. But if i cancel my programm and restart it, i will only take 5ms for 1000 entrys (Long positions maintain the same)

Why is that? Can someone help me fixing this issue?

The logical explanation is that 1st launch need to actually read the file, the other launch get file from memory cache, so much faster.

Also the 2nd time, you don't need to write data if I read correctly.

If you want to get something better, you can try to have sequential stuff like :

private static final int CHUNK_SIZE=512*8*1024;  // 4Mb chunk

private RandomAccessFile raf; 
private long currentChunk=-1;
private byte[] chunk=new byte[CHUNK_SIZE];

public void flush() throws Exception{
    raf = new RandomAccessFile(new File("./db.bin"),"rw");
    List<Long> c=something();

    c.stream().sorted().forEach(this::process);

    saveChunk();
}

public void process(long l) {
    try {
        if (l/8/CHUNCK_SIZE!=currentChunk) {
            saveChunk();
            loadNextChunk();
        }

        long posInMem=(l/8) - (CHUNK_SIZE*currentChunk);
        byte b=chunk[(int)posInMem];
        chunk[(int)posInMem]=editByte(b,(int)l % 8);
    }catch(Exception e) {
        e.printStackTrace();
    }
}

private void loadNextChunk()throws Exception {
    currentChunk++;
    raf.seek(currentChunk*CHUNK_SIZE);
    raf.readFully(chunk, 0, CHUNK_SIZE);
}

private void saveChunk() throws Exception {
    if (currentChunk<0)return;
    raf.seek(currentChunk*CHUNK_SIZE);
    raf.write(chunk, 0, CHUNK_SIZE);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM