既然零拷贝直接内存这么快,这么好为啥不都用? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
aiqier
V2EX    程序员

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

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

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

    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  
       020-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     Solana     2237 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 29ms UTC 01:05 PVG 09:05 LAX 17:05 JFK 20:05
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86