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

既然零拷贝直接内存这么快,这么好为啥不都用?

  •  2
     
  •   aiqier · 2020-05-25 09:21:53 +08:00 · 9278 次点击
    这是一个创建于 1647 天前的主题,其中的信息可能已经有所发展或是发生改变。

    零拷贝省去了从内核缓冲区到进程缓冲区的时间,这么好的优化没有在任何地方使用,我猜测一定有什么弊端才会导致不会所有读写都使用零拷贝,但是究竟是啥弊端,个人只想到是内核缓冲区和进程缓冲区没有分开,不方便管理。

    46 条回复    2020-07-23 13:59:18 +08:00
    tachikomachann
        1
    tachikomachann  
       2020-05-25 09:23:52 +08:00 via Android
    跟 cpu 有 L1 L2 L3 cache 差不多道理吧?
    hoholiday
        2
    hoholiday  
       2020-05-25 09:27:19 +08:00 via Android
    安全、性能和复杂度的考虑
    jinzhongyuan
        3
    jinzhongyuan  
       2020-05-25 09:41:14 +08:00
    插眼关注,等大佬
    nekoneko
        4
    nekoneko  
       2020-05-25 09:42:41 +08:00
    正如二楼所说
    lllyyy
        5
    lllyyy  
       2020-05-25 09:52:06 +08:00
    比较难管理吧
    tabris17
        6
    tabris17  
       2020-05-25 09:55:21 +08:00
    并发写怎么办?
    pdog18
        7
    pdog18  
       2020-05-25 09:56:46 +08:00
    @hoholiday 我猜也是这个原因,但是为什么不能通过“封装”来避免这个问题呢?是哪个方面导致了无法规避掉这些因素?(这可能很蠢,但是真心想知道原因)
    zy445566
        8
    zy445566  
       2020-05-25 09:58:17 +08:00 via Android
    为什么引用传递比值传递快,反而值传递用的多?
    pdog18
        9
    pdog18  
       2020-05-25 10:06:01 +08:00
    @zy445566 为什么啊
    yulitian888
        10
    yulitian888  
       2020-05-25 10:08:10 +08:00   ❤️ 7
    这个问题就好像在问,大别墅那么好,为什么大家不买呢?
    好,意味着是需要付出代价的!
    零拷贝只能解决性能问题,带来的是 CPU 承担更多的负载,内存管理增加了更复杂的安全逻辑。副作用是提高了编写、测试难度,降低了可维护性。这两点决定了做应用开发的人不会涉足,只有特定领域,比如驱动开发,或者高性能计算的时候才会选择去用。
    而我们都知道,大部分开发岗位做的是应用系统开发,而不是底层驱动。写一大堆高性能复制对应用系统的性能提升,很容易就被一个编写不良的业务循环给抵消了,何苦呢!靠这种技术提高性能,不如好好培养算法把业务实现写得更优雅来得实在
    dilu
        11
    dilu  
       2020-05-25 10:09:38 +08:00
    好≠合适
    mscb
        12
    mscb  
       2020-05-25 10:10:34 +08:00 via Android
    心智负担(逃
    hheedat
        13
    hheedat  
       2020-05-25 10:14:50 +08:00
    @yulitian888 “带来的是 CPU 承担更多的负载”,CPU 的负载为啥会变高?
    zjsxwc
        14
    zjsxwc  
       2020-05-25 10:14:57 +08:00
    楼主也是来布道 rust 吗,除了显式实现 copy 特性外,默认赋值都是直接转移所有权的不做拷贝,还有借用这些当然是直接传引用了也不拷贝,也就是说基本都是零拷贝哟,美滋滋
    ShadowStar
        15
    ShadowStar  
       2020-05-25 10:28:33 +08:00   ❤️ 12
    10 楼基本在胡说八道,零拷贝技术就是为了绕开 CPU 的处理。
    零拷贝需要硬件(比如常见的:网卡)支持 DMA ( Direct Memory Access )操作。
    yulitian888
        16
    yulitian888  
       2020-05-25 10:31:44 +08:00
    @hheedat 嗯,好吧,我这个表达是不对的。CPU 减少了“复制”这个行为的消耗,总负载肯定是降低的。但是增加了内存共享上锁的操作。前者后者需要更复杂的编写和测试。这样表达才对。
    behanga
        17
    behanga  
       2020-05-25 10:35:05 +08:00
    从你平常最常见的常见说起, 如何处理同步问题?
    belowfrog
        18
    belowfrog  
       2020-05-25 10:35:15 +08:00 via iPhone
    nginx 的 sendfile 不就是应用么
    fcten
        19
    fcten  
       2020-05-25 10:45:49 +08:00   ❤️ 1
    从内核态到用户态零拷贝需要内核支持,不是说零拷贝就可以零拷贝的。内核空间和用户空间隔离是内核安全性的基石,不然就变 DOS 了。
    90928yao
        20
    90928yao  
       2020-05-25 10:50:29 +08:00
    这个问题我也很疑惑
    xxzs
        21
    xxzs  
       2020-05-25 10:50:33 +08:00 via Android
    D 这个问题就类似于 DPDK 性能好,为什么大部分人不用,还是继续用 kernel 提供的 socket? 本质上就是兼容移植通用代码的额外负担。PS4 这些机器性能 PC 但游戏性能比 PC 强也是如此
    feather12315
        22
    feather12315  
       2020-05-25 11:00:51 +08:00
    DMA 提供在外设和存储器之间或者存储器和存储器之间的高速数据传输,无法在 A 内存地址的数据拷贝至 B 内存地址时候用吧?

    是这样的话:CPU 总耗时会降低,但是内核执行( sys )时间会增加,服务器多数为非抢占式调度,此情况下拷贝数据过多不就产生假死了吗?
    ShadowStar
        23
    ShadowStar  
       2020-05-25 11:03:20 +08:00   ❤️ 3
    @yulitian888 和内存共享上锁没有必然关联。
    零拷贝,本质上是硬件可以直接写内存( DMA );而不需要内核从硬件读取、再写入内存。
    当硬件直接将数据写入内存后,可以通过直接映射物理内存到用户空间的方式,来绕过内核。

    楼主所说的“不都用”的问题,我觉得主要原因是早期的硬件,以及目前的部分硬件不支持这种 DMA 操作。
    scnace
        24
    scnace  
       2020-05-25 11:21:09 +08:00 via Android
    用 unsafe 的操作,就要自己做好 unsafe 的准备
    fihserman123
        25
    fihserman123  
       2020-05-25 11:32:16 +08:00
    Java 和 JVM 的意义是什么?封装 C++/C 对底层的操作,让程序员专心于业务逻辑。直接内存已经是反 JVM 设计思想了。对 JVM 来说直接内存并没有什么特别的,从 JDK1.0 就有了。 直接内存只是 JDK1.4 JVM 给程序员开的一个口子。不要总以为直接内存好,JVM 的 GC 管理它不香吗?
    fihserman123
        26
    fihserman123  
       2020-05-25 11:33:02 +08:00
    啊 我好像看错题了.....
    fihserman123
        27
    fihserman123  
       2020-05-25 11:35:53 +08:00
    楼主说的关乎于权限问题。如果一般应用都能直接读取内核区,那操作系统如何确保应用程序的安全性?
    dartabe
        28
    dartabe  
       2020-05-25 11:39:38 +08:00
    @feather12315 dma 可以的 总线地址都能访问

    dma 的问题是适合大批量 连续的地址的数据 不然如果分成各种小段的话还是需要 cpu 下不同的指令
    2kCS5c0b0ITXE5k2
        29
    2kCS5c0b0ITXE5k2  
       2020-05-25 11:40:18 +08:00
    性能 !== 绝对
    feather12315
        30
    feather12315  
       2020-05-25 11:47:15 +08:00   ❤️ 1
    @feather12315 #22

    我找了下资料,标准的 x86 不支持内存与内存之间的 DMA 拷贝 ( ARM 支持),但也有 IOAT DMA 这种方式支持。
    DMA 无法使用 CPU cache,存在一致性问题。

    如果仅仅想“把文件 A 的内容拷贝到文件 B”那里,我记得看过一篇文章,有开发者提议合并 open()、read()、wirte()、close()四个系统调用,因为系统调用耗时也高。

    Reference:
    1. https://www.zhihu.com/question/266921250
    2. https://biscuitos.github.io/blog/DMA/
    lewis89
        31
    lewis89  
       2020-05-25 11:47:54 +08:00   ❤️ 1
    @fihserman123 #27 Netty 的直接内存区域泄漏 估计搞得很多 Javaer 神经质了..
    fihserman123
        32
    fihserman123  
       2020-05-25 12:01:27 +08:00
    @lewis89 <<<<<<QAQ<<<<<<<<
    ljzxloaf
        33
    ljzxloaf  
       2020-05-25 12:07:54 +08:00
    不好同步吧,共享读,副本写
    zhuangzhuang1988
        34
    zhuangzhuang1988  
       2020-05-25 12:20:01 +08:00   ❤️ 1
    为何 c++性能这么高, 为何重视性能的后端还都用 java.
    bitdepth
        35
    bitdepth  
       2020-05-25 12:58:07 +08:00 via iPad
    1. 小尺寸無優勢,這邊有一份郵件表明 512KiB 下無意義,很多變數都是如此,甚至 Copy on write 的開銷都太高了
    2. 設備相容和資料對齊問題(多數可解決)
    3. CPU cache 和 MMU 建表開銷很大,反正都是要過 CPU 不如一開始就用 CPU (場景決定)

    大致考量如此
    mogami18
        36
    mogami18  
       2020-05-25 13:48:31 +08:00
    这么好的优化没有在任何地方使用
    回楼主,我是搞 RDMA 相关 research 的,TensorFlow 大规模集群 training 的时候,如果后台指定了 RDMA 通信,Tensor 们的传输就是 zero-copy 了。相关实现请看 https://github.com/tensorflow/networking/tree/master/tensorflow_networking/verbs,用 ibverbs 做的
    ivechan
        37
    ivechan  
       2020-05-25 13:51:37 +08:00
    @ShadowStar 说的没错。其实现在 类 DMA 也挺常见的了。
    比如 RDMA 在各种云计算厂商底层里会作为一个优化手段使用,
    阿里云去年还发表了一篇 X-RDMA 的文章,也有相关的 talk 。
    不过,底层领域大多数人不关心,所以不了解也挺正常。
    mogami18
        38
    mogami18  
       2020-05-25 13:56:20 +08:00
    @ivechan 基本上系统顶会 osdi, sosp, nsdi 什么的,从 15 年就 RDMA 就开始流行了。Datacenter RPCs can be General and Fast, NSDI'19 。这篇 paper 讲了很多基于可 DMA 的网卡优化 Datacenter 中 RDMA 连接池性能等问题
    chinuno
        39
    chinuno  
       2020-05-25 14:01:09 +08:00 via Android
    我觉得最大的问题是限制了应用场景吧。如果你只是需要读文件直接通过网络传输,那用零拷贝是最好的。
    但是业务场景往往都是需要应用对数据进行处理才把数据送出去,比如数据先加密再进行传输。而做这步操作必然需要把数据从拷贝到用户态缓冲区来处理,所以无法利用上零拷贝的优势
    RubyJack
        40
    RubyJack  
       2020-05-25 15:06:43 +08:00
    大部分场景 瓶颈不在这里的拷贝
    BigDogWang
        41
    BigDogWang  
       2020-05-25 16:28:13 +08:00
    虽然我不懂,但是好多人答非所问。
    瓶颈不在这里,业务影响更大,那底层做好封装不就完了?跟瓶颈在哪有啥关系呢?
    这里不是瓶颈,那里不是瓶颈,所以优化都不用做了
    3dwelcome
        42
    3dwelcome  
       2020-05-25 16:37:57 +08:00
    这就和用不用网卡上的读写缓存一样,你写 socket,可以指定自己管理缓存区,系统的可用可不用,自己可选择。
    有时候,需要的并不是实时网络内容反馈,而是避免大量网络包拥堵。
    个人觉得算法存在肯定有其理由,就类似 list 和 vector 数组管理,没有谁优谁劣,要看使用场景的,没有一个是绝对优势。
    diveIntoWork
        43
    diveIntoWork  
       2020-05-25 16:58:11 +08:00   ❤️ 1
    考虑场景,假如不需要对磁盘数据修改,那么 sendfile 系统调用直接发送数据到 io 设备,零拷贝;如果需要对磁盘数据修改,普通 io 要四次拷贝,也可以 mmap 内存映射,这样只需要三次拷贝;如果只是单纯数据读取 /写入,那你零拷贝就没用了,因为你肯定要经过数据从磁盘->内核态->用户态的过程;

    所以不是所有的 IO 场景,都可以用上零拷贝,要搞清楚零拷贝是为了解决什么问题而存在的
    JohnSmith
        44
    JohnSmith  
       2020-05-25 17:01:50 +08:00
    @zjsxwc #14
    lewinlan
        45
    lewinlan  
       2020-05-25 22:40:46 +08:00 via Android
    为什么 html css js 这么烂 所有人都在用它?
    MenghanKing
        46
    MenghanKing  
       2020-07-23 13:59:18 +08:00
    总结来说,常规文件操作为了提高读写效率和保护磁盘,使用了页缓存机制。这样造成读文件时需要先将文件页从磁盘拷贝到页缓存中,由于页缓存处在内核空间,不能被用户进程直接寻址,所以还需要将页缓存中数据页再次拷贝到内存对应的用户空间中。这样,通过了两次数据拷贝过程,才能完成进程对文件内容的获取任务。写操作也是一样,待写入的 buffer 在内核空间不能直接访问,必须要先拷贝至内核空间对应的主存,再写回磁盘中(延迟写回),也是需要两次数据拷贝。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3543 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 10:54 · PVG 18:54 · LAX 02:54 · JFK 05:54
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.