性能优化的方法和技巧:系统

Sina WeiboBaiduLinkedInQQGoogle+RedditEvernote分享




从系统层次去优化系统往往有比较明显的效果。但是,在优化之前,我们先要问一问,能否通过扩展系统来达到提高性能的目的,比如:

  • Scale up: 用更强的硬件替代当前的硬件
  • Scale out: 用更多的部件来增强系统的性能

使用更强的硬件当然和优化没有半点关系,但是如果这是一个可以接受的方案,为什么不用这个简单易行的方案哪?替换硬件的风险要比改架构,改代码的风险小多了,何乐而不为?

Scale out的方案就有一点麻烦。它要求系统本身是支持scale out,或者把系统优化成可以支持scale out。不管是哪一种选择,都不是一个简单的选择。设计一个可以scale out的系统已经超出了本文所要关注的范围,但是,scale out应该是系统优化的一个重要方向。

下面会讨论一些常见的系统优化的方法,如果还有其他没有提到的,也欢迎读者指出来。

1) Cache

  • Cache是什么?Cache保存了已经执行过的结果。
  • Cache为什么有效?一是可以避免计算的开销(比如SQL查询的开销);二是离计算单元更近,所以访 问更快(比如CPU cache)。
  • Cache的难点在哪里?一是快速匹配,这涉及到匹配算法选择(一般用哈希表),Cache容量(哈希表的容量影响查找速度);二是替换策略(一般使用LRU或者随机替换等等)。
  • Cache在哪些情况下有效?毫无疑问,时间局部性,也就是当前的结果后面会用到,如果没有时间局部性,Cache就不能提高性能,反而对性能和系统架构有害处。所以在系统设计之初,最好是审视一下数据流程,再决定是否引入Cache层。

2) Lazy computing

Lazy computing(延迟计算),简而言之,就是不要做额外的事情,特别是无用的事情。最常见的一个例子就是COW(copy on write),可以参考这个链接http://en.wikipedia.org/wiki/Copy-on-write

  • COW是什么?写时复制。也就是说fork进程时,子进程和父进程共享相同的代码段和数据段,如果没有写的动作发生,就不要为子进程分配新的数据段(通常在fork之后,会有exec,用新的代码段和数据段替换原来的代码段和数据段,所以复制父进程的数据段是没有用的)。
  • COW为什么有效?一是可以节省复制内存的时间,二是可以节省内存分配的时间(到真正需要时再分配,虽然时间不会减少,但是CPU的使用更加均匀,避免抖动)。
  • COW的难点在哪里?一是引用计数,多个指针指向同一块内存,如果没有引用计数,内存无法释放;二是 如何知道哪块内存是可以共享的?(在fork的例子里面,父进程,子进程的关系非常明确,但是在有些应用里面,需要查找能够共享的内存,查找需要花时间)

Lazy computing在哪些情况下有效?目前能想到的只有内存复制。用时分配内存算不算哪?用时分配内存不能节省时间,但是可以节省空间。静态内存对时间性能有好处;动态内存对空间性能有好处。就看目标是优化哪个性能了。

3) Read ahead

Read ahead (预读),也可以称之为pre-fetch(预取)。就是要提前准备所需要的数据,避免使用时的等待。

  • Read ahead是什么?可以参考http://en.wikipedia.org/wiki/Readahead,这个是讲文件预读的。CPU里面也有pre-fetch(CPU预取需要仔细安排,最好是能够填充流水线,所以需要多次尝试才有结果)。
  • Read ahead为什么有效?Read ahead可以减少等待内存的时间。其实相当于把多个读的动作集合成一个。这个和网络里面的buffering或者sliding window有异曲同工之妙。停-等协议是最简单的,但是效率也最低。
  • Read ahead的难点在哪里?预读多少才合适?预读窗口的大小需要根据负载,文件使用的多少等因素动态调整。预测的成功与否关系的性能。所以这并不是一个简单的优化方法。
  • Read ahead在哪些情况下有效?毫无疑问,空间局部性。没有空间局部性,read ahead就失去了用武之地。用错了,反而会降低性能。

4) Hardware assist

Hardware assist (硬件辅助),顾名思义,就是用硬件实现某些功能。常见的,比如加密,解密;正则表达式或者DFA engine,或者规则查找,分类,压缩,解压缩等等。逻辑简单,功能确定,CPU intensive的工作可以考虑用硬件来代替。

  • Hardware assist为什么有效?协处理器可以减轻CPU的工作,而且速度比CPU做要快(这个要看情况,并不是任何情况下都成立)。Hardware assist和Hardware centric的设计完全不同,不能混为一谈。在Hardware assist的设计里面,主要工作还是由软件完成;而hardware centric就是基于ASIC的设计方案,大部分工作是有硬件来完成。
  • Hardware assist的难点在哪里?一是采用同步还是异步的方式与硬件交互(通常是异步);二是如何使硬件满负荷工作,同时又避免缓冲区溢出或丢弃(这个要安排好硬件和软件的节奏,使之协调工作);还有就是硬件        访问内存的开销(尽量硬件本身所带的内存,如果有的话)。

5) Asynchronous

Asynchronous(异步)。同步,异步涉及到消息传递。一般来说,同步比较简单,性能稍低;而异步比较复杂,但是性能较高。

  • Asynchronous是什么?异步的含义就是请求和应答分离,请求和应答可以由不同的进程或线程完成。比如在 TCP协议的实现里面,如果滑动窗口是1,那么每次只能发送一个字节,然后等待应答;如果增加滑动窗口,那么一次可以发送多个字节,而无需等待前一个字节的应答。这样可以提高性能。
  • Asyncrhonous为什么有效?异步消除了等待的时间,可以更有效利用带宽。
  • Asynchronous的难点是什么?一是如何实现分布式的状态机?由于请求和应答双方是独立的,所以要避免状态之间有依赖关系,在无法消除状态之间的依赖关系时,必须使用同步消息(比如三次握手);二是应答来了之后,        如果激活原来的执行过程,使之能够继续执行。
  • Asynchronous在哪些情况下有效?很明显,状态之间不能有依赖关系,同时需要足够的带宽(或者窗口)。

6) Polling

Polling(轮询)。Polling是网络设备里面常用的一个技术,比如Linux的NAPI或者epoll。与之对应的是中断,或者是事件。

  • Polling为什么有效?Polling避免了状态切换的开销,所以有更高的性能。
  • Polling的难点是什么?如果系统里面有多种任务,如何在polling的时候,保证其他任务的执行时间?Polling 通常意味着独占,此时系统无法响应其他事件,可能会造成严重后果。
  • Polling在哪些情况下有效?凡是能用事件或中断的地方都能用polling替代,是否合理,需要结合系统的数据流程来决定。

7) Static memory pool

Static memory pool(静态内存)。如前所述,静态内存有更好的性能,但是适应性较差(特别是系统里面有多个 任务的时候),而且会有浪费(提前分配,还没用到就分配了)。

  • Static memory pool为什么有效?它可以使内存管理更加简单,避免分配和是否内存的开销,并且有利于调试内存问题。
  • Static memory pool的难点在哪里?分配多大的内存?如何避免浪费?如何实现O(1)的分配和释放?如何初始化内存?
  • Static memory pool在哪些情况下有效?一是固定大小的内存需求(通常与系统的capacity有关),内存对象的大小一致,并且要求快速的分配和释放。

系统层次的优化应该还有很多方法,能想起来的就这么多了(这部分比较难,酝酿了很久,才想起来这么一点东西^-^),读者如果有更好的方法,可以一起讨论。性能优化是关注实践的工作,任何纸上谈兵都是瞎扯,与读者共勉。

参考资料:

1:http://en.wikipedia.org/wiki/Copy_on_write

2:http://en.wikipedia.org/wiki/Readahead

3:http://en.wikipedia.org/wiki/Sliding_window

4:http://en.wikipedia.org/wiki/Asynchronous_I/O

5:http://en.wikipedia.org/wiki/Coprocessor

6:http://en.wikipedia.org/wiki/Polling_(computer_science)

7:http://en.wikipedia.org/wiki/Static_memory_allocation

8:http://en.wikipedia.org/wiki/Program_optimization

9:  http://en.wikipedia.org/wiki/Scale_out

(没有打分)

雁过留声

“性能优化的方法和技巧:系统”有19个回复

  1. 陈怀临 于 2011-05-06 8:14 上午

    说个玩笑话。读kernelchina的文章总让人想起我这个年纪的人在上初高中的时候看黄色大毒草“少女之心”【现在想多纯洁的书呀】。看了之后狂喜;看完之后不过瘾。

    许多东西要再深一点,再深一点。。。。

  2. kernelchina 于 2011-05-06 8:22 上午

    水平有限,总结了这点东西,也是力所能及。弯曲看评论,我也是来学习的。弯曲是一个交流,学习的平台,比公司里面学到的多。

  3. kevin 于 2011-05-06 10:03 上午

    quantitive is the most important thing.

    If you can’t measure it, you can’t control it.

    –Huailin

  4. symantec 于 2011-05-06 11:25 上午

    许多东西要再深一点,再深一点。。。。

    ————————

    太深了,弯友们会受不了的。。。。

  5. symantec 于 2011-05-06 3:52 下午

    确实比较浅,看的不过瘾

    其实如果加一些统计数据就好了,比如 某硬件升级,或者Cache算法改进等,带来的系统性能有多少变化。是具体哪一类性能的变化?

    系统性能至少有三个参数指标:计算,存储,网络
    再细分,就是 CPU MEMORY and NETWORK;还可以再细分,比如CPU,浮点计算性能,查找性能,与CHACHE之间的带宽,等等,。。。。一层一层往下剥,,,如果有一些数据做为支撑,就离出书不远了。

    盼后期文章。。。关注!

  6. 一场春梦 于 2011-05-06 4:37 下午

    本人初涉江湖,欣然见各位高人煮酒论剑,饶有情趣,这番景象不可多见。

  7. westermann 于 2011-05-06 4:38 下午

    看过一本老毛子写的书.好像是卡巴司机写的(不过似乎同杀毒那个司机不是一个人).那本书集中在如何更有效的利用memory带宽,减小访问延迟,当然少不了cache了.司机感觉就是个数据帝,几乎所有的case都有柱形图比较等.以前读书时就买了,以为是本烂书,里面没有一处优化是站在算法优化层面,都是假设算法优化已经做到封顶后在ram bank层程序员所需要做的一些优化,和chipset直接相关.一开始居然还有dram ras cas等介绍,以为作者凑字赚稿费.后来才慢慢体会到这本书的独特.

  8. westermann 于 2011-05-06 4:39 下午

    晕,书名居然被meta data掉了.叫Code Optimization – Effective Memory Usage

  9. qingjiegong 于 2011-05-06 8:48 下午

    学习一下。看完指令,数据手册,还不知道下一步干什么。看来明灯是多么重要啊。以后要quantitiv it 才行啊。

  10. 文海 于 2011-05-06 11:11 下午

    也许kernelchina什么时候出一本书,专门讲性能调优的,我也可以买一本捧场。

    也许kernelchina什么时候出一工具,专门做性能调优的,我也可以捧场。

    既有.txt,又有.exe,赞!

  11. 三千大千世界 于 2011-05-07 9:14 上午

    谢谢kernelchina的分享!
    问个弱智的问题:什么是系统的性能?可以简单的理解为系统运行的速度吗?个人感觉性能包含的东西很多,比如对数据报文的处理速度,进程间交互的效率,甚至状态机的流转等等。而且不同的OS上还有差异,比如Linux上user space跟kernel space的交互。有些时候优化了速度但是确牺牲了其他东西,需要trade off。

    “许多东西要再深一点,再深一点。。。。”
    要不首席给我们再来点更深的?:)让我们过过瘾。

  12. jhs 于 2011-05-07 9:36 上午

    好文章。
    不要挑战首席,首席深不可测,你受不了的

  13. 陈怀临 于 2011-05-07 9:45 上午

    太深了也不一定好。。。

    不度量,则深浅皆误,后来官人要三思:-)

    鉴定完毕。

  14. papa 于 2011-05-08 2:36 上午

    我们要看系统、架构、算法、代码、指令、硬件按层面归纳的优化。能解剖一只麻雀更好^_^

  15. papa 于 2011-05-08 2:46 上午

    我们还要看复杂系统的瓶颈查找过程,以及相关的进程、内存、文件、IO的优化。最重要是我们要看针对不同目标的优化,例如时间、空间、公平性、通量等等单个或者多个目标的优化^_^

  16. playmud 于 2011-05-09 1:19 上午

    似乎还没涉及到深入的问题吧,只是做了一个婚前教育。

  17. true 于 2011-05-11 8:05 下午

    同感这句话。
    ==========================
    性能优化是关注实践的工作,任何纸上谈兵都是瞎扯,与读者共勉。

  18. if 于 2011-06-08 2:54 上午

    又一次拜读,
    从时间维度看:预读,延迟。动态,静态。
    从空间维度看:cache,硬件加速,数据离散。
    从M2M维度看: 异步,轮询。
    是不是在空间维度可增加:批处理,数据离散?
    不过,无论从何种维度看,都可用首席的一句话来衡量:系统是否是健康的? 系统是个整体,不能厚此薄彼,静态内存多了,那么动态申请的效率必定下降,而如何一个健康比例需要依据业务场景逐步调试,正符合某大师常说的:系统是长出来的。 :)

  19. yyxx 于 2011-07-05 9:15 上午

    非常受益,感谢分享.
    基本上可以理解,不过还是需要一段实践的消化.

    性能优化还是挺难的一个题.有些子模块即便优化得再好,整个设备体系架构不行,都是白搭的.

    尤其是异步这个问题,确实会把原本简单的问题弄得很复杂,比较难搞…..