
零拷贝省去了从内核缓冲区到进程缓冲区的时间,这么好的优化没有在任何地方使用,我猜测一定有什么弊端才会导致不会所有读写都使用零拷贝,但是究竟是啥弊端,个人只想到是内核缓冲区和进程缓冲区没有分开,不方便管理。
1 tachikomachann 2020-05-25 09:23:52 +08:00 via Android 跟 cpu 有 L1 L2 L3 cache 差不多道理吧? |
2 hoholiday 2020-05-25 09:27:19 +08:00 via Android 安全、性能和复杂度的考虑 |
3 jinzhongyuan 2020-05-25 09:41:14 +08:00 插眼关注,等大佬 |
4 nekoneko 2020-05-25 09:42:41 +08:00 正如二楼所说 |
5 lllyyy 2020-05-25 09:52:06 +08:00 比较难管理吧 |
6 tabris17 2020-05-25 09:55:21 +08:00 并发写怎么办? |
7 pdog18 2020-05-25 09:56:46 +08:00 @hoholiday 我猜也是这个原因,但是为什么不能通过“封装”来避免这个问题呢?是哪个方面导致了无法规避掉这些因素?(这可能很蠢,但是真心想知道原因) |
8 zy445566 2020-05-25 09:58:17 +08:00 via Android 为什么引用传递比值传递快,反而值传递用的多? |
10 yulitian888 2020-05-25 10:08:10 +08:00 这个问题就好像在问,大别墅那么好,为什么大家不买呢? 好,意味着是需要付出代价的! 零拷贝只能解决性能问题,带来的是 CPU 承担更多的负载,内存管理增加了更复杂的安全逻辑。副作用是提高了编写、测试难度,降低了可维护性。这两点决定了做应用开发的人不会涉足,只有特定领域,比如驱动开发,或者高性能计算的时候才会选择去用。 而我们都知道,大部分开发岗位做的是应用系统开发,而不是底层驱动。写一大堆高性能复制对应用系统的性能提升,很容易就被一个编写不良的业务循环给抵消了,何苦呢!靠这种技术提高性能,不如好好培养算法把业务实现写得更优雅来得实在 |
11 dilu 2020-05-25 10:09:38 +08:00 好≠合适 |
12 mscb 2020-05-25 10:10:34 +08:00 via Android 心智负担(逃 |
13 hheedat 2020-05-25 10:14:50 +08:00 @yulitian888 “带来的是 CPU 承担更多的负载”,CPU 的负载为啥会变高? |
14 zjsxwc 2020-05-25 10:14:57 +08:00 楼主也是来布道 rust 吗,除了显式实现 copy 特性外,默认赋值都是直接转移所有权的不做拷贝,还有借用这些当然是直接传引用了也不拷贝,也就是说基本都是零拷贝哟,美滋滋 |
15 ShadowStar 2020-05-25 10:28:33 +08:00 10 楼基本在胡说八道,零拷贝技术就是为了绕开 CPU 的处理。 零拷贝需要硬件(比如常见的:网卡)支持 DMA ( Direct Memory Access )操作。 |
16 yulitian888 2020-05-25 10:31:44 +08:00 @hheedat 嗯,好吧,我这个表达是不对的。CPU 减少了“复制”这个行为的消耗,总负载肯定是降低的。但是增加了内存共享上锁的操作。前者后者需要更复杂的编写和测试。这样表达才对。 |
17 behanga 2020-05-25 10:35:05 +08:00 从你平常最常见的常见说起, 如何处理同步问题? |
18 belowfrog 2020-05-25 10:35:15 +08:00 via iPhone nginx 的 sendfile 不就是应用么 |
19 fcten 2020-05-25 10:45:49 +08:00 从内核态到用户态零拷贝需要内核支持,不是说零拷贝就可以零拷贝的。内核空间和用户空间隔离是内核安全性的基石,不然就变 DOS 了。 |
20 90928yao 2020-05-25 10:50:29 +08:00 这个问题我也很疑惑 |
21 xxzs 2020-05-25 10:50:33 +08:00 via Android D 这个问题就类似于 DPDK 性能好,为什么大部分人不用,还是继续用 kernel 提供的 socket? 本质上就是兼容移植通用代码的额外负担。PS4 这些机器性能 PC 但游戏性能比 PC 强也是如此 |
22 feather12315 2020-05-25 11:00:51 +08:00 DMA 提供在外设和存储器之间或者存储器和存储器之间的高速数据传输,无法在 A 内存地址的数据拷贝至 B 内存地址时候用吧? 是这样的话:CPU 总耗时会降低,但是内核执行( sys )时间会增加,服务器多数为非抢占式调度,此情况下拷贝数据过多不就产生假死了吗? |
23 ShadowStar 2020-05-25 11:03:20 +08:00 @yulitian888 和内存共享上锁没有必然关联。 零拷贝,本质上是硬件可以直接写内存( DMA );而不需要内核从硬件读取、再写入内存。 当硬件直接将数据写入内存后,可以通过直接映射物理内存到用户空间的方式,来绕过内核。 楼主所说的“不都用”的问题,我觉得主要原因是早期的硬件,以及目前的部分硬件不支持这种 DMA 操作。 |
24 scnace 2020-05-25 11:21:09 +08:00 via Android 用 unsafe 的操作,就要自己做好 unsafe 的准备 |
25 fihserman123 2020-05-25 11:32:16 +08:00 Java 和 JVM 的意义是什么?封装 C++/C 对底层的操作,让程序员专心于业务逻辑。直接内存已经是反 JVM 设计思想了。对 JVM 来说直接内存并没有什么特别的,从 JDK1.0 就有了。 直接内存只是 JDK1.4 JVM 给程序员开的一个口子。不要总以为直接内存好,JVM 的 GC 管理它不香吗? |
26 fihserman123 2020-05-25 11:33:02 +08:00 啊 我好像看错题了..... |
27 fihserman123 2020-05-25 11:35:53 +08:00 楼主说的关乎于权限问题。如果一般应用都能直接读取内核区,那操作系统如何确保应用程序的安全性? |
28 dartabe 2020-05-25 11:39:38 +08:00 |
29 2kCS5c0b0ITXE5k2 020-05-25 11:40:18 +08:00 性能 !== 绝对 |
30 feather12315 2020-05-25 11:47:15 +08:00 @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/ |
31 lewis89 2020-05-25 11:47:54 +08:00 @fihserman123 #27 Netty 的直接内存区域泄漏 估计搞得很多 Javaer 神经质了.. |
32 fihserman123 2020-05-25 12:01:27 +08:00 @lewis89 <<<<<<QAQ<<<<<<<< |
33 ljzxloaf 2020-05-25 12:07:54 +08:00 不好同步吧,共享读,副本写 |
34 zhuangzhuang1988 2020-05-25 12:20:01 +08:00 为何 c++性能这么高, 为何重视性能的后端还都用 java. |
35 bitdepth 2020-05-25 12:58:07 +08:00 via iPad 1. 小尺寸,有一份件表明 512KiB 下意,很多都是如此,甚至 Copy on write 的都太高了 2. 相容和料(多可解) 3. CPU cache 和 MMU 建表很大,反正都是要 CPU 不如一始就用 CPU (景定) 大致考量如此 |
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 做的 |
37 ivechan 2020-05-25 13:51:37 +08:00 @ShadowStar 说的没错。其实现在 类 DMA 也挺常见的了。 比如 RDMA 在各种云计算厂商底层里会作为一个优化手段使用, 阿里云去年还发表了一篇 X-RDMA 的文章,也有相关的 talk 。 不过,底层领域大多数人不关心,所以不了解也挺正常。 |
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 连接池性能等问题 |
39 chinuno 2020-05-25 14:01:09 +08:00 via Android 我觉得最大的问题是限制了应用场景吧。如果你只是需要读文件直接通过网络传输,那用零拷贝是最好的。 但是业务场景往往都是需要应用对数据进行处理才把数据送出去,比如数据先加密再进行传输。而做这步操作必然需要把数据从拷贝到用户态缓冲区来处理,所以无法利用上零拷贝的优势 |
40 RubyJack 2020-05-25 15:06:43 +08:00 大部分场景 瓶颈不在这里的拷贝 |
41 BigDogWang 2020-05-25 16:28:13 +08:00 虽然我不懂,但是好多人答非所问。 瓶颈不在这里,业务影响更大,那底层做好封装不就完了?跟瓶颈在哪有啥关系呢? 这里不是瓶颈,那里不是瓶颈,所以优化都不用做了 |
42 3dwelcome 2020-05-25 16:37:57 +08:00 这就和用不用网卡上的读写缓存一样,你写 socket,可以指定自己管理缓存区,系统的可用可不用,自己可选择。 有时候,需要的并不是实时网络内容反馈,而是避免大量网络包拥堵。 个人觉得算法存在肯定有其理由,就类似 list 和 vector 数组管理,没有谁优谁劣,要看使用场景的,没有一个是绝对优势。 |
43 diveIntoWork 2020-05-25 16:58:11 +08:00 考虑场景,假如不需要对磁盘数据修改,那么 sendfile 系统调用直接发送数据到 io 设备,零拷贝;如果需要对磁盘数据修改,普通 io 要四次拷贝,也可以 mmap 内存映射,这样只需要三次拷贝;如果只是单纯数据读取 /写入,那你零拷贝就没用了,因为你肯定要经过数据从磁盘->内核态->用户态的过程; 所以不是所有的 IO 场景,都可以用上零拷贝,要搞清楚零拷贝是为了解决什么问题而存在的 |
45 lewinlan 2020-05-25 22:40:46 +08:00 via Android 为什么 html css js 这么烂 所有人都在用它? |
46 MenghanKing 2020-07-23 13:59:18 +08:00 总结来说,常规文件操作为了提高读写效率和保护磁盘,使用了页缓存机制。这样造成读文件时需要先将文件页从磁盘拷贝到页缓存中,由于页缓存处在内核空间,不能被用户进程直接寻址,所以还需要将页缓存中数据页再次拷贝到内存对应的用户空间中。这样,通过了两次数据拷贝过程,才能完成进程对文件内容的获取任务。写操作也是一样,待写入的 buffer 在内核空间不能直接访问,必须要先拷贝至内核空间对应的主存,再写回磁盘中(延迟写回),也是需要两次数据拷贝。 |