读《Optimized-C++》

分类: 阅读

之前在Oreilly的Safari Books Online中看到过,大概浏览了目录,感觉讲解的角度非常全面,于是就加到了收藏书单里。然而电子书不常看,尤其是Safari的安卓端异常难用,读到的机会就更少了。

后来我从独墅湖图书馆偶遇过这本书的英文版《Optimized C++》,便拿起来翻看了几章。当时正苦恼于内存池相关的问题,通过目录找到相关章节仔细读了读,却感到一点失落。这本书并没有讲的很深,读罢,也没有“恍然大悟”的感觉。于是,那天没有决定借走这本书。

再后来,也就是前一阵,我又在计划重构C++代码,为了让这次重构更高效,达到更好的质量,索性把这本书借回来翻看一下。即使这本书的内容新意不多,它系统性的总结分析也有助于我巩固性能调优相关的技术知识。

事实上,当真正沉下心来从头到尾地仔细读一本书时,终究会发现它能够带给自己一些新的见解,更重要的是能让自己意识到一些以前未曾想到的事情。

可以想象,这本书一开始肯定要宣扬性能优化。简而言之,作者的意思大概是性能优化是必要的,是可以接受的,但也是需要被度量的。

它必要,因为它能带来经济效益,提高用户体验;它可以接受,这是针对“实现业务即可,就算优化也要等到最后”这种民间常常流行的说法,即优化性能并不费劲,可以在开发过程中穿插进行;它需要被度量,是为了把优化的力量集中在占比更大的功能上,防止过度优化。

后面,作者就从各个方面展开了讲,比如字符串、算法、内存分配、库、输入输出、并发等等。每一个方面都有很多需要注意的性能问题,大概每个问题也都能写出一小本书来——所以这本书对于很多小点,只能是简单说说,仅供了解,引起注意;不是每一点都有详尽的例子让人深刻领悟,也很难让人模仿实践。

可以说读来读去,总感觉C++标准库的不完善很令人头痛。如果标准库能更好用,更灵活,想必很多性能瓶颈也可以避免。多少用C++的人都会选择从头造轮子,想来也是C++标准库不完善的一个体现。

当然,我认为还有很多容易出现性能瓶颈的地方,也源自语言本身的设计缺陷,这有历史遗留的问题。毕竟C++最初想要兼容C语言,而且一直以来都保持良好的向后兼容性,在设计上确实要束手束脚一些。

看看隔壁Rust一上来就有好用的Slice,而C++到了17才有string_view,20才有span……然而这些东西是非常有助于写出高性能代码的——减少不必要的字符串、数组等的拷贝。另外,因为兼容性考虑,C++害怕破坏已有代码,虽然逐渐加了一些有助于增强代码正确性的语法特性,比如const、override等等,但都不是强制性的,有时就很鸡肋。而Rust往往默认最简的写法是约束最强的,比如let声明的是常量,let mut声明的才是变量。Rust的理念是让开发者为越灵活(危险)的操作付出越大的代价。C++似乎正相反,简单的写法约束最少,容易引发错误,对于新手入门来说也许还算友好——至少能让程序编译运行,不像Rust新手可能几天内都无法写出一个能够成功编译的程序。可是当程序越发复杂,性能需求也逐渐增加后,就会发现C++程序中有很多需要返工的部分,比起后期返工调试调优的代价,开发过程中额外的心智负担根本算不上什么。

吐槽了这么多C++,并不是否定它。它有它的历史局限性。C++已经很棒了,能够一直活跃至今,而且十分上进地进行现代化。正是C++,让很多几十年的代码仍然焕发着活力,为当今世界的高效运转贡献力量。所以,它的价值绝对不容否定,​学习它,使用它也绝对不会是不好的选择。

对了,在图书馆中看到另一本书,大概浏览了目录,涉及了很多C++语言不尽如人意的地方。尤其是看到有一些ABI、API相关的部分,与我近期工作密切相关,其中有不少观点正切中痛点,想必值得一读。《Imperfect C++》,先记一下,日后待读。

最后,还是要把话题扯回来,仍然要推荐一下《Optimized C++》这本书,尤其是对于很多可能对C++11之后新特性了解不深的读者,以及从未尝试过性能调优、对性能问题了解不深的读者。

这本书能够带领读者从性能这个角度,全面地了解C++11以来的各种语法和标准库的特性,并借助包含这些特性在内的各种各样的工具,初步实践很多性能调优手法,全面了解C++程序中潜在的性能问题。

书摘

  • 阿姆达尔定律(Amdahl’s Law)
$$ 总体性能提升 = \frac{1}{(1-优化部分占比)+\frac{优化部分占比}{优化部分的性能提升}} $$
  • Precision是精度,精度高意味着多次测量偏差小。
  • Accuracy是准度,准度高意味着测量值接近真实。
  • 展平的数据结构更具性能优势。

……

以上是对我最有启发的几点。
​书中大部分都是琐碎的知识点,就不摘太多了。

何况作者也说,性能调优是个实验学科,还是得动手呀!