非常开心今天跟大家介绍一下从系统工程的角度怎么看OpenStack,以及从系统工程的角度怎么样去做一些优化。我在GCC的社群当中负责多个片区,所以今天的议题中会到一些代码。

    

给大家介绍一下Outline:什么是performance,为什么做performance,怎么处理performance。

 

什么是performance?相信大家在教科书里面学到很多特殊的名词,直白一点就是跑起来感觉速度是快还是慢,这就是使用者体验。简单地讲performance就是使用体验。手机划屏是钝还是很顺利,感受完全不一样。

 

为什么需要performance?身为RD有时候可能会听到一个词叫做先求有再求好,东西先做出来,许多事情如果没有东西那一点用都没有。身为RD,我每天都在看代码,每天都在写代码。很多东西当我们写出来之后你就希望它好,但你有这个东西,别人也有这个东西,当大家在同一个水平线上,都没有办法让它变得更好的时候,请问你的差异在哪里?

 

一个I手机跟一个A手机,客观来说通常I手机跑起来舒服一些,这就是它的差异化。为什么它这么贵?用起来这么舒服?其实在于除了划屏的感觉还有其他让你的使用感受超越其它手机的。为什么要做performance的答案就是要做出差异化,让使用者的体验更好。


我们从哪些地方改善performance?最简单可以分两个角度,一是从硬件的角度,这个我们今天不谈。我们今天谈的是从software的角度怎么改善performance。

 

这是最简单、最基础的一个概念。OpenStack最基本的就是Compute、Networkig和Storage,但实际上从系统工程的角度看,OpenStack还有非常多的东西。大家知道绝大多数的OpenStack在运营的过程中需要相关咨询。今天我想改善performance,以前的老师告诉我要好好思考题目怎么写,怎样在这上面做优化,但是永远都是在最上面去做。中间的怎么来的?你可能抓一大堆相关的东西,但永远都探取不到那部分。如果做得不够好,能够提升的效能非常有限。

 

在继续往下走之前,我先讲一下所谓的语言还有效能之间的关系。计算机看得懂的语言是什么?是机器语言,01010101。其实Bug一词的由来是这样的——在最早的时候计算机是一个大房间,有一大堆的开关,写代码的时候是控制开关,对应着010101。有一天,一只飞蛾跑进去,把它打死了造成短路,这就是代码世界当中的第一个Bug。

 

最早的时候机器语言就是0101去完成的,速度最快,不需要做其它多余的事情。可是用0101跟计算机沟通是非常麻烦而且不直接的,所以有了汇编语言。现在所用的全部都是高级语言,C,C++、Python、Java,但是高级语言计算机看不懂,一定要有一个翻译的动作,也就是说一定要把高级语言翻译成机器语言。谁来做这件事情?第一个是Compiler,第二个是Interpreter。

 

Compiler的目的是将高级语言编写的原始代码一次全部翻译成机器语言的目的代码,Interpreter将高阶语言所编写的原始代码,一边翻译成机器语,一边执行其代码的档案。

 

上面这一张图更明显,直接编译成目的代码档案,载入内存后直接执行。它直接执行的就是这一堆0101的目的代码。

 

左边是cpython,中间的部分是Python的原始代码,其中一个档案是C code写成的。当Python执行的时候,系统解析左边的C code,Runtime进行翻译并在内存里模拟行为。

 

整个系统当中,如果improve python interpreter的速度比较快,整体的效率就会比较高。Library也是用C code写成的,也有改善的机会,甚至到直接跟硬件沟通的Operating System、Hardware,这样整体效能就有所提升。

 

现在的Compiler编译能力比你想象的还要强大。第一就是让performance变得比较好,或者是让C code变得比较小。

 


左上角是三层的循环,加减乘除。如果你只是正常用Optimization的-O0去编译的话,你会看到后面的结果,很明显至少有三层循环,直接产生左下角的答案。编译可认知到多余的循环是没必要的,所以效能大幅提升。

 

另外一个例子也是一个循环,但是它做了很多的运算。当你做这些的时候,你能够模块化地去做,但是它能够直接告诉你答案。为什么?省略多余的加法乘法除法的计算,performance直接就提升了。

 

到目前为止,绝大部分的Packages都是用这个连出来的。根据不同的需求,它有很多不同的optimization level,适应各种不同的场合,甚至还有单独开关的东西。现在的GCC已经有超过300多个optimization的face,开关就有三百多种可能。所以说其实我们是有很多种不同的可能去做优化。当然,你会想既然有这么多的优化,那我就全开下去,得到一个全部都最好的optimization的东西。抱歉,这件事情在Compiler的角度上根本没有办法做到。

 

为什么?举个例子,左边这个地方for的循环1-60,你想怎么样做最优化?我们用人脑去做一个最佳化。简单展开一下,让它每次走三步,里面的c就不再是一行而是三行。这个动作为什么做到优化?我们手动可以做到优化,因为它展开的层数如果越多,循环的跳转行为与比较次数就越少。左上角至少有60次,左下角每次条三个都要跑20次,是不是整个速度上就差了?如果是的话,那我干脆一次都不要它跳,但是请注意,在某个临界值因为cache的影响,performance反而会大幅下降。

 

另外一个例子是function inline。调用三次swap,就至少有三次跳过去再跳回来的动作。如果每次的swap都被内联展开在main函数中,减少swap函数调用,单一函数中大量操作易造成寄存器数量的短缺而造成常态性对内存的访问。这会让performance严重下降。

 

大家想我怎么挑?难道我就直接用Oto吗?难道没有再改善的空间吗?其实有的,来看看有哪些功能可以做到。GCC PGO,也称为feedback Directed Optimization(FDO)。或许你有时候会看到一些学术的文件写它是有不同的说法,但是单词的意思都是一样,就像这张图Source code先编译一次然后再重新编译一次。

 

当然光说不行,一定要试试看。我们试试看用Python。在这个环境中,用的是CentOS 7.3和GCC 4.8.5。

 

这是第一个简单的数据。你们可以看到在右下角大概可以提升10%或者13%。

 

除此之外再仔细看一下整个Python所提供的,平均来看是10%~13%。如果我懂得使用Compiler,我自己做一个调整,编译出来的数据就可以使它提升Python 13%。

 

有人会问那最多只能提升13%吗?还可以再快一点,就以Python这个Performance来做的话,甚至可以做到30%。

从这些数据可以看出,至少可以提升10%左右的Python。如果应用在不同的地方,OpenStack用到的其它软件应用都可以重新编译,重新打包。

 

总结一下,我们都知道云计算平台需要有一个稳定的底层系统的支持,然而底层系统是我们所忽略的一环,它存在着很多可以改善的空间。许多软件平台甚至是核心都是由C/C++写成的,因此我们需要善用编译器的力量。如果我们能够了解系统工程的运作原理的话,就可以从上到下提升稳定度与优化性能,做出差异化,让你与其他人不同。谢谢!