达人是按什么标准来对程序进行调优的呢?如果有规律可循固然好,但达人的调优方法都来源于日常积累起来的经验和知识,所以没有这方面经验和知识的人是很难掌握的。
人在接触陌生的事物时,为了能理解这个事物,一般都会结合以前的经验和知识来进行类推。对没有经验的人来说,那些连类推也无法读懂的信息,就如同魔法一般。
在本书中,笔者将会与大家一起,分享他根据自己多年的经验和知识摸索出来的调优方法,但具体如何调优则因人而异。接下来请出另外一位对本书有诸多贡献的松冈先生。
松冈:大家好,我是松冈。下面我们来听听片山老师的见解。但在此之前,由于我和片山老师解决问题的方向不同,所以我觉得有必要先聊聊彼此的研究领域,或者说是解决问题的前提吧。首先请片山老师先来介绍。
片山:大家好,我是片山。我呢,主要擅长Linux 环境中的文本处理。在开发环境下喜欢打开几个vi,只要显示屏足够大就可以了。如何将事物精简是USP 研究所的基本理念。所使用的语言以C 语言为主,不使用C++。
松冈:我主要在Windows 环境下进行开发工作,使用C++、C#、Java等面向对象语言,因此在Visual Studio 和Eclipse 等集成开发环境下进行编程。所涉及的领域主要在图像方面,擅长对图像进行高效处理。
松冈:看来,我们彼此所擅长的开发环境和研究领域不一样。我呢,打算站在读者的角度就可能出现的疑问来与片山老师讨教讨教。
片山:刚才不是说想听我的见解吗?怎么现在变成向我提问了?有点不祥的预感啊。
松冈:就当作是提问吧,不然让你一个人拉锯怎么行呢。这样你一言我一语也挺好的。
片山:所以嘛,通常的提问方式是我说完“这里要这样做”,然后你就问:“为什么要这样做呢?讲解一下可以吗?”是这样吗?
. 松冈:主要是因为这本书是从一个专家的角度来看高效编程的,而读者并不是专家呀。不是有个词叫“通常情况”嘛,这个“通常”靠的是平时积累起来的经验和知识,所以对那些没有这方面经验和知识的人来说,简直就像是克拉克的第三法则:超越理解范围,感觉像是魔法一样无法理解。
片山:那我是魔法师?
松冈:有个词叫做“天才”,或者说是“宗师”。
片山:性能优化是一种技术而非魔法。
松冈:在普通人看来,专家就像是魔法师,像是宗师。我呢,学习武术大概有20 多年了,在武术界,对段位相差两个级别的人来说,级别低的人是完全无法理解级别高的人的。能理解比自己高两个段位的技术理论的人是非常少见的。
片山:这大概是由经验和知识决定的吧。
松冈:是的。系统化的经验和知识就像武术中的套路,这个套路不是靠看就能悟透的。而且为了保证自家套路不被其他套路抄袭,各家也想了很多办法。这样一来,即使被其他流派模仿了,也模仿不到其中的精髓。所谓精髓是指心法,是武术不被抄袭的关键所在。
片山:哦……心法呀……
松冈:是的。所以即使是被其他流派的人抄袭过去了,然后研究其中的技术理论,以为能找到破解的方法,但实际上他们看到的都只是假象,他们破解的招数也根本不起作用。想想日本武术可是日本战国时期的产物啊,那是性命攸关的事……
片山:的确是这样!
松冈:所以,门生看到老师的动作,心想“老师那样做,我这样做就能打败他”,却一下子就被老师踢飞了。他不知道,原来老师早就把他的心思看得一清二楚啦。
片山:很有趣呢,将经验系统化。
松冈:回到我们刚才说的话题上来,其实这个经验系统化与编程也是有关联的。在编程的领域里,经验和知识也是在通过各种方法逐步系统化,而面向对象的设计模式就是其中一种。
片山:也许如此。但我的确不赞同使用类。我的立场是:即使不使用某种架构也能得到更为精简的程序。
松冈:而我则是在非常积极地使用面向对象。但与片山老师刚好相反,我不用设计模式。不过,即使不用也能做出点事情。
片山:“ 也能做出点事情” ?那就表示这能做的事儿也是以经验和知识作后盾的啰?
松冈:大概是这样的吧。起初看到设计模式的时候就有种意料之中的感觉。我用类来组装成部件,与设计模式结合起来,发现可以通过生成差分法编程来追加功能,所以我认为是能做点什么的。
片山:我并不喜欢用C++ 的类来创建实例的指针。那样会产生很多看不见的成本,如果无法估计程序所需成本,那要进行高效编程是比较困难的。
松冈:的确,在看不见的地方消耗成本会很不舒服。听说在某些项目中,将实例应用到方法时,复制构造函数会带来很大的开销。单复制这一个动作就会变得十分缓慢,以至于不能回复到原态。
片山:是啊,如果不了解处理系统在做些什么,就不能理解其中哪些部分产生了运行开销。更可怕的是不了解这些情况的人还会因此废弃实例,从而造成回收垃圾(garbage collection)的开销。
松冈:但即使是使用虚拟机的Java 和C#,内存管理与垃圾回收对程序员来说也都是不可见的吧。
片山:我认为还是对内存的碎片等多留点心会比较好。
松冈:关于这一部分内容,大家可以去看Ruby之父松本先生的书 ,相当有趣。话说片山先生曾经开发过编译器吧。
片山:是的。对于编译器如何分配CPU 寄存器等我比较熟悉。在用C语言进行编程时,对编译器的使用也是相当小心的。
松冈:那也就是说,C 语言是最能直接分配CPU 资源的语言了。除了汇编以外。
片山:C 语言似乎更像是汇编的语法糖。
松冈:以前,C 编译器还没有怎么优化过,我们在使用的时候都是一边想象着编译器会生成什么样的代码一边编程,也是一边编程一边诱导编译器:“生成这样的代码吧。”
片山:这样的话,在高效编程时就必须掌握处理系统的相关知识。
松冈:片山老师使用什么样的编译器呢?
片山:我主要是用GNU C(GCC)。根据工作的需要有时也会用其他编译器,但还是以GCC 为主。
松冈:那关于GCC 生成代码的各种偏好你都了解吧?
片山:那是必须的。
松冈:我主要是用微软的编译器,偶尔也用英特尔的。英特尔的编译器只有在使用自品牌CPU 时才能达到非常棒的优化效果,犹如手工汇编。
片山:那是当然的。因为它们非常了解CPU 内部的运作嘛。
松冈:就好像是在优化的时候,一边计算着CPU 的内部成本一边生成代码似的。
片山:使用GCC 不会优化到那种地步。如果对特定的CPU 进行了优化的话,就会偏离GCC 的初衷——应对各种各样的CPU。
在序中,两位专家都阐述了各自的立场,在后面的内容中也会以对话的形式呈现两位不同的观点。