Unity开发元老抨击:C++ 20新功能造成编译缓慢与调试构建性能低落

负责Unity绘图引擎架构与发展的元老工程师Aras Pranckevičius,在个人博客发布不看好C++ 20新功能Ranges的文章,而其在推特上的贴文也引来许多游戏开发工程师表达相同的感受。他提到,C++的编译时间与调试构建(Debug Build)性能非常重要,但是C++ 20的新功能Ranges却让这两者都大幅增加。

11月ISO C++委员会在圣地亚哥召开了有史以来最大规模的会议,就C++ 20的语言更新草案进行讨论,而决议之一便是决定加入Ranges概念。 Ranges是即将在C++ 20加入的新语法功能,Ranges用来帮助操作范围概念,能够让开发者简单的迭代具有开始和结束范围,并回传行为类似迭代器的对象。 Ranges能够让语法更为简洁,使程序代码阅读者不再需要自己解析复杂的for循环逻辑。

而主推Ranges和Concepts进入标准函数库的Eric Nieble,在自己的博客发布标题为Standard Ranges的文章,然而却在Aras Pranckevičius发布评论之后,引来了部分游戏开发者的讨论,多数表达了反对意见。

That example for Pythagorian Triples using C++20 ranges and other features sounds terrible to me. https://t.co/9T6RvNzifQ

And yes I get that ranges can be useful, projections can be useful etc. Still, a terrible example! Why would anyone want to code like that?!

— Aras Pranckevičius (@aras_p) 2018年12月23日

Aras Pranckevičius使用目前最佳近似实例,由Eric Nieble撰写的range-v3,与简单版C++进行比较,他指出,C++ 20可能的问题至少有两个,编译时间与执行性能。他以Eric Nieble在自己博客解释Ranges功能的毕氏三元数为例,以使用Ranges的C++编译程序代码,编译时间长达2.92秒,比简单版C++的0.064秒还要多2.85秒,他表示,现代的CPU可以在3秒的时间,进行很大量的操作,像是以Clang在调试模式中编译完整数据库引擎SQLite只要0.9秒,他质疑,编译毕氏三元数的5行程序代码,却需要编译整个数据库引擎的3倍时间。

Aras Pranckevičius指出,编译时间是编译大型C++程序代码库痛苦的来源,他随意枚举Chromium、Clang/LLVM或UE4项目,都能让开发者轻易的体验这件事,他指出,编译时间就是一个C++待解决的大问题,而且应该在列表中排名之一,但是整个C++社群却假装这不是个问题。

由于在每个C++版本都会有更多的内容被放进标头档中,而且不像是C只在头文件放入结构声明或是函数原型,C++会把整个模板化的类别和函数都加入。 range-v3是一个大小1.8MB的程序标头档,而且即便预编译标头档,也只省下了0.7秒,整个编译时间仍然长达2.24秒,比简单版C++仍然长2.1秒。

另外,Aras Pranckevičius也提到,非优化构建性能也是非常重要的,在毕氏三元数的例子中,拥有Ranges的C++执行时间为300毫秒,而简单版的C++却只要2毫秒,也就是说执行性能慢了150倍,他认为,执行时间多2到3倍可以接受,慢10倍以上可能代表无法使用,而有Ranges的C++却是百倍以上。

执行性能对于游戏程序来说非常重要,Aras Pranckevičius表示,或许在部分应用调试模式中慢10或100倍的时间,只是比较扰人,但是在游戏中,当每秒只有2个影格,则已经不是感觉上的问题,而是从根本上无法达到玩游戏的体验。即便构建优化后的执行性能与简单版本相同,但Aras Pranckevičius提到,要对优化的程序代码调试非常困难,这增加了工作难度。

相较之下,以C#实例毕氏三元数,使用Mono编译器编译需要0.2秒,而简单版的C#则是0.17秒,两者相去不远。 Aras Pranckevičius认为,虽然C++ 20被称为现代C++,但事实上这些变化,并没有因为是“现代”而变得更好,大多数游戏开发人员都还停留在C++ 11、14或是17的版本,无论C++ 20增加了什么新功能,编译时间与调试构建性能太差就毫无用武之地。

尽管Aras Pranckevičius的批评引起不少游戏开发者的声援赞同,但range设计目的是为了简化复杂的C++程序代码,超多行数的大型程序代码是否会如简单几行的毕氏三元数程序一样,遭遇到同样严重的性能问题,Aras Pranckevičius则没有进一步举例实测。