零拷贝省去了从内核缓冲区到进程缓冲区的时间,这么好的优化没有在任何地方使用,我猜测一定有什么弊端才会导致不会所有读写都使用零拷贝,但是究竟是啥弊端,个人只想到是内核缓冲区和进程缓冲区没有分开,不方便管理。
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 7
这个问题就好像在问,大别墅那么好,为什么大家不买呢?
好,意味着是需要付出代价的! 零拷贝只能解决性能问题,带来的是 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 12
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 1
从内核态到用户态零拷贝需要内核支持,不是说零拷贝就可以零拷贝的。内核空间和用户空间隔离是内核安全性的基石,不然就变 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 3
@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 2020-05-25 11:40:18 +08:00
性能 !== 绝对
|
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/ |
31
lewis89 2020-05-25 11:47:54 +08:00 1
@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 1
为何 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 1
考虑场景,假如不需要对磁盘数据修改,那么 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 在内核空间不能直接访问,必须要先拷贝至内核空间对应的主存,再写回磁盘中(延迟写回),也是需要两次数据拷贝。
|