专栏首页程序人生软件性能调优:看数据,还是谈概念?

软件性能调优:看数据,还是谈概念?

上周写了「想让服务器跑得快,并不是换个编程语言那么简单」,很多朋友的留言歪了楼:论性能,C语言甩Python数倍到数十倍,你说和编程语言没关?拜托,程序君只是说,不是换个编程语言那么简单。这种留言,我都是建议看了原文再说。还有朋友留言说她转到朋友圈里炸了锅,大家众口一词:不谈zero copy,谈什么服务器性能!优化系统调用有个毛用!

对此,我只能说,buzz word荼毒太深,以至于大家陷进去,遇到问题,先摆个伟光正的大道理出来。我想,很多开口闭口zero copy的主,也许连zero copy是何物都没搞清楚。

我们看wikipeidia上的定义:

"Zero-copy" describes computer operations in which the CPU does not perform the task of copying data from one memory area to another. This is frequently used to save CPU cycles and memory bandwidth when transmitting a file over a network.

很清楚,zero-copy是当数据需要从内存的A点拷到B的时候,CPU不参与这个过程,也就是不通过调用 memcpy(),实现内存拷贝。这个过程一般是device driver来完成,通过DMA(direct memory access)绕过CPU在外设(一般是NIC,也就是网卡)和主存中做乾坤大挪移。放一张图:

至于DMA是怎么工作的,怎么发起,怎么通知CPU,cache coherence怎么处理,这就不是本文要讲的内容。

当然,这是狭义的zero copy,一般更广义的zero copy还包括在DMA结束后的整个数据的生存周期里,数据尽可能地少拷贝(绝对不是不拷贝哦)。

我们看Kernel如何收包(简化版):

  • 驱动初始化时,为NIC分配ring buffer。
  • NIC收到报文后,找到下一个空闲的buffer,将其DMA到buffer指定的内存里,同时发送interrupt,告知Kernel。(第一次zero copy)
  • Kernel处理这个interrupt,将这个buffer据为己有做后续处理,然后新分配一个buffer,还给driver。(第二次zero copy)。
  • 接下来交给TCP stack处理(因为咱们讲的是服务器开发,一般是TCP服务器)。TCP是个stream based protocol,在这里,报文的排序,组包(把TCP头去掉,payload连接起来供application使用)等等,根据实现的不同,也许需要copy至少一次。另外,如果自己作为发送端,由于需要考虑潜在的retransmit,一般也会copy一份到retransmit queue里。(网络设备专门优化不在此讨论范围之内)
  • 之后交给application处理,这涉及到kernel space到user space的切换。将application的buffer和kernel的buffer映射起来不是一件简单的事情,所以这里一般也会有一次copy。

当然,现在有跳过kernel的stack,从NIC直接DMA到user space的技术,但那一般是网络厂商干的勾当。我觉得咱们做一个服务器软件,还是不要抢人家TCP stack的生意,否则你会把自己玩死。

基本上,这些动作都发生在application无法控制的kernel里。好处是:当你 recv() 的时候,你拿到了一个只包含有 TCP payload 的 重组好的,可以线性阅读的buffer。你只需要关心application level的逻辑。你能控制的,也只有之后,尽可能少的copy这个buffer。嗯,我们兜了这么一大圈,终于回到之前的问题:不谈zero copy,谈什么服务器性能,谈什么优化系统调用!

无奈的是,我们只能控制application level的zero copy。

假设我们写了一个 HTTP server。大多数HTTP请求头都不会太大,除非是post一个文件,或者应用服务器设置了巨大的cookie。我们假设平均而言整个请求大小是4k(这个假设没有价值,只是为了比对),而我们的 server 稍稍2b一些,除了正常处理中的copy之外,还会把整个请求 memmcpy() 一遍。为公平起见,我们不和那些占用时间比较长的系统调用比较,就和 gettimeofday() 比一比。主体代码如下:

(顺手写下的两行代码,如有纰漏,敬请原谅)

带着gprof编译运行,然后查看看结果:

(注意:这个结果你最好自己写代码测一下,不同的环境可能不一样,我用的是digital ocean最小的instance,ubuntu 14.04)

哟,貌似 memcpy() 没有想象的那么慢嘛,同样10million调用次数,比 gettimeofday() 慢一点点而已。

那问题来了,你是费尽心思去优化散落在各处小小的,基本上不可避免的copy呢,还是1s调用一次 gettimeofday(),而不是来一个包就调用一次,省却99.99%的调用呢?

你是会把发送response时分别两次发送header和body的两个 write() 合并成一个,来减少几十ms级的网络round trip的延迟,还是费尽心思去优化散落的copy呢?

你是会通过使用 stracegprof,以及 systemtap 等各种工具,追溯到真正性能所在的瓶颈,然后对症下药,还是不假思索地跳将出来:一切不谈zero-copy而论performance的服务器软件都是耍流氓!

当你看不起系统调用带来的损耗时,你是否又知道,当你苦苦追寻zero-copy的时候,kernel已经尽力在提供各种扩充的系统调用来尽可能让某些应用场景快起来?比如 sendfile()?如果你的response是个静态文件,你可以通过这个系统调用轻松实现zero-copy?

写这么些,不是证明我有多对,我的知识也有可能是错的。只是当我们遇到问题的时候,是真正测量还是人云亦云,吐几个buzz word就自认为解决问题了呢?

至少,我写上一篇文章的时候,我还拿strace亲测了一下nginx在首次访问和再次访问同一URI下系统调用的不同呢?

不管你怎么看待题图中的人物,但我喜欢:「我不是为了输赢,我只是认真」这句话。performance是认认真真不断测量和调整打造出来的,不是拍脑门想出来的。

本文分享自微信公众号 - 程序人生(programmer_life),作者:Tyr

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2015-07-27

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 能花钱的,就不要花时间

    如果要寻找这个星球上最抠门的群体,那么一定非程序员们莫属了。有个笑话是找对象要找程序员:『挣得多,花的少;常加班,死的早』。 在创业之前,我也是个抠门的主。公司...

    tyrchen
  • 软件随想录

    (一) 软件领域有个叫格林斯潘的哥们,估计大家都不怎么熟悉,但下面这句话写过代码可能没几个不知道: Any sufficiently complicated C...

    tyrchen
  • 代码结构的演进

    过年了,各种公众号都在玩拜年,玩红包,甚至在玩喜羊羊,连程序君订阅的一些技术类的公号也不能免俗。作为大年三十还在苦逼上班的程序君,自然不会放过这个绝好的机会写点...

    tyrchen
  • python中的copy和deepcopy()

    结论:如果是可变类型如果是用copy.copy(a)的话则就是只是深拷贝外边的一层里边的一层列表就不是深拷贝了,就是直接和a的列表中的内层列表的id相同了 a...

    逐梦的青春
  • 谈抽象接口的重要性

    .pdf 抽象是架构师最基础最重要的能力之一。一名程序员要成长为架构师,首先要理解接口的重要性。但是对一个没有经验的人来说,他心中可能无法体会“接口”这两个字...

    一见
  • ReentrantReadWriteLock读写锁及其在 RxCache 中的使用

    Lock 是相当于 synchronized 更面向对象的同步方式,ReentrantLock 是 Lock 的实现。

    fengzhizi715
  • 《计算机图形学基础(OpenGL版)》勘误表

    T2=[cos600∘sin600∘0−sin600∘cos600∘0001]=[−1/2−3/203/2−1/20001]T_2= \left[ \begin...

    步行者08
  • 保护 Node.js 项目的源代码

    SaaS(Software as a Service,软件即服务),是一种通过互联网提供软件服务的模式。服务提供商会全权负责软件服务的搭建、维护和管理,使得他们...

    保利威视频云
  • 【周末漫谈】如何清晰地找到合适的数据挖掘算法?

    一名数据科学家所需要具备的技能组合。我们可以发现,和典型的大数据开发者或者商业分析专员相比,他的职责是多种技能和经验的有效组合。 ? 再看看数据科学家应有的技术...

    钱塘数据
  • 2019年6月 阿里技术面试题集锦(28道含答案)

    为帮助开发者们提升面试技能、有机会入职阿里,云栖社区特别制作了这个专辑——阿里巴巴资深技术专家们结合多年的工作、面试经验总结提炼而成的面试真题这一次整体放出。并...

    搜云库

扫码关注云+社区

领取腾讯云代金券