应用程序可以通过posix_fadvise()
来告诉内核访问文件的模式,建议内核如何进行IO以达到最优性能(如名字所示,它仅仅是一个建议或期望,内核不承诺遵守)。可用的模式有:POSIX_FADV_NORMAL
,POSIX_FADV_SEQUENTIAL
,POSIX_FADV_RANDOM
,POSIX_FADV_NOREUSE
,POSIX_FADV_WILLNEED
,POSIX_FADV_DONTNEED
。本文看一看它们的行为。
POSIX_FADV_RANDOM
(1)
先做个测试:
bs (KiB) |
read_ahead_kb (KiB) |
max_sectors_kb (KiB) |
avgrq-sz (KiB) |
---|---|---|---|
16 | 8 | 4 | 4 |
16 | 8 | 64 | 8 |
16 | 32 | 64 | 16 |
说明:
- 测试是fio发起的,顺序读但设置
fadvise_hint=random
(这样是为了突出POSIX_FADV_RANDOM
的作用);文件系统是ext4;bs
如表中所示; read_ahead_kb
:/sys/block/sda/queue/read_ahead_kb;max_sectors_kb
:/sys/block/sda/queue/max_sectors_kb;avgrq-sz
:iostat观察到的请求大小;
结果是:
$$ AvgRqSz = min(bs,ReadAheadKB,MaxSectorsKB) $$
一些文档说POSIX_FADV_RANDOM
用于禁止read ahead。可是,要是read ahead被禁止的话,请求应该是page-by-page的(见linux 3.19.8 mm/filemap.c:do_generic_file_read()
),也就是avgrq-sz=4KiB
(通常page size是4KiB),而实际上并不是如此,这是为什么呢?
找到patch-187024才发现,在过去的版本中的确是page-by-page的,因为这很低效,现在已经修改了:
1 | This fixes inefficient page-by-page reads on POSIX_FADV_RANDOM. |
现在ra_pages=0
(完全禁止read ahead,page-by-page的读)只在multi-page读没有帮助或者应该被避免的地方:
1 | - it's ramfs/tmpfs/hugetlbfs/sysfs/configfs |
现在POSIX_FADV_RANDOM
的语义不再是禁止read ahead,而是禁止基因算法,从而如实地把应用程序的read IO发下去:
1 | POSIX_FADV_RANDOM actually want a different semantics: to disable the |
也就是直接发送应用程序的请求大小(bs
),当然,也受限于read_ahead_kb
和max_sectors_kb
(三者中取最小)。
看这个patch的diff:
linux 3.19.8 mm/fadvise.c:fadvise64_64
:
1 | switch (advice) { |
linux 3.19.8 mm/readahead.c:page_cache_sync_readahead()
:
1 | if (!ra->ra_pages) |
就是POSIX_FADV_RANDOM
不再设置ra_pages=0
,而是设置FMODE_RANDOM
(FMODE_RANDOM
就是这个patch新引入的);在page_cache_sync_readahead()
中就不会立即返回(立即返回就会page-by-page的读),而是检查FMODE_RANDOM
,从而进行强制read ahead。