V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
pabno
V2EX  ›  程序员

Linux I/O 块对齐的疑问

  •  
  •   pabno · 2020-04-13 00:26:05 +08:00 · 2548 次点击
    这是一个创建于 1472 天前的主题,其中的信息可能已经有所发展或是发生改变。

    最近在看《 linux 系统编程》书的时候,有提到一个概念,就是 read/write 数据时,数据的大小最好与块大小对齐:比如块大小 1k,那么每次调用 read/write 的数据大小最好是 1k 的整数倍,这样会提高性能

    里面提到了一个测试:针对 2m 的数据,每次写 1130 字节会比每次写 1024 字节表现更差,因为 1130 不是 1k 的倍数,即没有与块对齐

    这里有个疑问: 每次 read/write 实际上都是针对页缓存操作的,后续由操作系统负责页回写到设备。那用户进程每次写的 batch 更大,不是意味着系统调用会更少,整体开销不是会更少吗?跟块设备进行交互的是块读取和块写入,而这个过程并不是发生在 read/write 的流程里的(不阻塞的意思),而是由内核处理, 那么块对齐的优势是体现在哪个方面?

    还是说我哪个点理解有错?

    10 条回复    2020-04-13 11:25:19 +08:00
    Mirana
        1
    Mirana  
       2020-04-13 00:58:13 +08:00
    io 分为 buffer 写和非 buffer 写,由 open 的时候带的参数控制
    May725
        2
    May725  
       2020-04-13 00:59:28 +08:00
    我的理解是这样的,
    假如要读 5k 数据,块大小 1k,如果按照每次读 1k,只需要读 5 次即可完成,累计从磁盘读出 5k 的数据。
    如果每次读 1.5k , 则要读 5/1.5 ,取整要读 4 次,由于是整块读,即 2k 读一次,至少累计从磁盘读出 7k 的数据。
    5k < 7k,所以优势就出来了。
    当然,这是基于 linux 的 read write 不带缓冲导致的,c 语言的 fread fwrie 这些是带缓冲的。

    以上有问题的话,希望大佬指出哈。
    kkk330
        3
    kkk330  
       2020-04-13 01:47:36 +08:00 via iPhone
    前不久也刚看完这本书,应该是第 67 页的内容,我的理解是
    1. 在用户空间对齐可以避免内核再进行对齐操作,这也是标准 io 库有缓冲区的原因之一,而且按书中描述“避免内核内其他冗余操作”,暗示应该还有其他操作
    2. 在对齐的前提下,写入的 batch 比较大确实会减少系统调用,可以测试一下,但我记得越大效果越不明显
    neoblackcap
        4
    neoblackcap  
       2020-04-13 02:25:43 +08:00
    是的,是对页操作。但是如果每页都是 512B,然后 1130 完全不对齐的话,那么就是每次需要操作 3 页,页用完了就需要换页,这个换页成本就高了。
    vk42
        5
    vk42  
       2020-04-13 03:43:08 +08:00
    @May725 Linux 的 read 和 write 是 buffered I/O,除非文件是用 O_DIRECT 打开的

    没看过书原文,从你介绍里面感觉书里的观点有点太死板了,实际应用可能有很多情况。不对齐可能有负面影响的例子很多,比如内核要做 padding,另外如果是 overwrite,写不满整页还要内核先把原有内容读出来等等
    pabno
        6
    pabno  
    OP
       2020-04-13 09:53:39 +08:00
    @May725 这里你可以理解有误,read/write 如果不指定 O_DIRECT 都话,都是带内核缓冲区的,fread/fwrite 是带了用户空间缓冲区
    pabno
        7
    pabno  
    OP
       2020-04-13 09:54:07 +08:00
    @Mirana 如果说是不经过 buffer 的,那倒是可以理解
    pabno
        8
    pabno  
    OP
       2020-04-13 10:04:15 +08:00
    @vk42 书中其实是有说明不指定 O_DIRECT 时,是带用内核缓冲区带。

    我的疑问是,用户进程每次其实都是在跟内核缓冲区交互,比如我写入 1.5 页数据时,虽然多出的 0.5 页数据没有对齐,但是在页缓存有预读机制。可能在写这 0.5 页时,他对应的那一页数据已经预读到内核缓冲区中了,这时其实就是内存到内存的复制了,这种场景是否对齐已经不重要了?

    另外如果系统页回写足够块,比如我写入 0.5 页数据后,页已经回写且淘汰了,我下次再写 0.5 页时,就要再一次读一页的数据到内核缓冲区并修改数据,然后页回写。这种场景页对齐就能减少开销。

    不知道我这理解是否正确
    vk42
        9
    vk42  
       2020-04-13 10:52:01 +08:00
    @pabno 离开具体案例分析意义不大,可能的情况太多了,而且现实中还有文件系统在中间。看书学习的话先知道有个块对齐的情况就行了
    pabno
        10
    pabno  
    OP
       2020-04-13 11:25:19 +08:00
    @vk42 确实,如果 case 太多,很难理解完全,理解完全也不一定真的有指导意义,只是有点好奇这个问题
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1239 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 23:28 · PVG 07:28 · LAX 16:28 · JFK 19:28
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.