Background:
I'm developing a database related program, and I need to flush dirty metadata from memory to disk sequentially. /dev/sda1 is volumn format, so data on /dev/sda1 will be accessed block by block and the blocks are adjacent physically if accessed sequentially. And I use direct I/O, so the I/O will bypass the caching mechanism of the file system and access directly the blocks on the disk.
Problems:
After opening /dev/sda1, I'll read one block, update the block and write the block back to the same offset from the beginning of /dev/sda1, iteratively.
The code are like below -
//block_size = 256KB
int file = open("/dev/sda1", O_RDWR|O_LARGEFILE|O_DIRECT);
for(int i=0; i<N; i++) {
pread(file, buffer, block_size, i*block_size);
// Update the buffer
pwrite(file, buffer, block_size, i*block_size);
}
I found that if I don't do pwrite, read throughput is 125 MB/s.
If I do pwrite, read throughput will be 21 MB/s, and write throughput is 169 MB/s.
If I do pread after pwrite, write throughput is 115 MB/s, and read throughput is 208 MB/s.
I also tried read()/write() and aio_read()/aio_write(), but the problem remains. I don't know why write after read at the same position of a file will make the read throughput so low.
If accessing more blocks at a time, like this
pread(file, buffer, num_blocks * block_size, i*block_size);
The problem will mitigate, please see the chart.
pwrite()
fills the cache, and if the nextpread()
is for different data, none of it is cached. Doing thepread()
after thepwrite()
allows data to be read directly from the disk's hardware cache. – Woe