C++性能及应用初步总结

  没有多少实际的C++大型项目经验,但想对其做一个全面的总结。但是碍于目前水平,先梳理出一个梗概,以后再做细化和完善,如有不当之处,恳请指正。

C++的性能 

先说说优点

说的人比较多,就直接罗列在此了。

  • 严谨、精确、数理化,其语法思路层次结构分明,逻辑明确,执行速度快。

  • C++标准在不断更新,在变得更加严谨、易用之时,保持着系统性。如果能熟练掌握全部C++标准(语法、标准库),你的代码编写工作会极其精炼.

  • 支持底层操作的。虽然许多底层操作的具体效果会随机器变化有所差异,也就是固有不可移植特性,但如果必要,依然可以使用它们编写程序、改善效率。

  • C++兼容C语言的几乎所有特征(部分极少的不严谨、存在歧义的特性被去除),你依旧采用C语言的思路,却可以轻易加入一个C++工程的开发。

  • C++拥有面向对象(OO)特性,“模板”等高度抽象化特性使得大型工程可以通过它进行整体管理。

  • 它考虑了兼容性,为连接其他语言的对象文件留有接口。

 

高性能的原因

 

相对运行于虚拟机语言(如C#/Java),C/C++直接以静态形式把源程序编译为目标平台的机器码。

一般而言,C/C++程序在编译及链接时可进行的优化最丰富,启动时的速度最快,运行时的额外内存开销最少。而C/C++相对动态语言(如Python/Lua)也减少了运行时的动态类型检测。

此外,C/C++的运行行为是确定的,且不会有额外行为(例如C#/Java必然会初始化变量),也不会有如垃圾收集(GC)而造成的不确定性延迟,而且C/C++的数据结构在内存中的布局也是确定的。

有时C++的一些功能会使程序性能优于C,当中以内联和模版最为突出,这两项功能使C++标准库的sort()通常比C标准库的qsort()快多倍(C可用宏或人手编码去解决此问题)。

另一方面,C/C++能直接映射机器码,之间没有另一层中间语言,因此可以做底层优化,例如使用内部(intrinsic)函数和嵌入汇编语言。

然而,许多C++的性能优点并非免费午餐,代价包括较长的编译链接时间和较易出错,因而增加开发时间和成本,这点稍后补充。

 

我进行了一个简单全局渲染性能测试(512x512像素,每像素10000个采样),C++ 1小时36分、Java 3小时18分、Python约18天、Ruby约351天。

 

不足和解决方案才是重点

1、程序容易崩溃?

和许多语言相比,C/C++提供不安全的功能以最优化性能,有可能造成崩溃。

但要注意,很多运行时错误,如向空指针/引用解引用、数组越界、堆栈溢出等,其他语言也会报错或抛出异常,这些都是程序问题,而不是语言本身的问题。

有些意见认为,出现这类运行时错误,应该尽量写入日志并立即中断,不该让程序继续运行,以免造成更大的影响(例如程序继续把内存中错误的数据覆写文件)。

若要容错,可按业务把程序分割为多进程,像Chrome或使用fork()的形式。然而,C++有许多机制可以减少错误,例如以string代替C字符串;

以vector或array(TR1)代替原始数组(有些实现可在调试模式检测越界);使用智能指针也能减少一些原始指针的问题。

另外,常遇到一些Bug,如成员变量未初始化等,有时会导致崩溃;而且调试版和发行版的行为也可能不同。

这些都是程序健壮性的问题,不仅跟语言相关,而且最主要还是在与程序员本身的素质。

2、C++编译速度很慢

错,是非常慢。C++可能是实用程序语言中编译速度最慢的。此问题涉及C++沿用C的编译链接方式,又加入了复杂的类/泛型声明和内联机制,使编译时间倍增。

在C++对编译方法改革之前(如module提案),可使用以下技巧改善:

  • 使用pimpl手法,因性能损耗应用于调用次数不多的类;
  • 仅包含必要头文件,并尽量使用及提供前置声明版本的头文件(如iosfwd);
  • 第三采用基于接口的设计,但须注意虚函数调用成本;
  • 采用unity build,即把多个cpp文件结合在一个编译单元进行编译;
  • 用分布式生成系统如IncrediBuild

3、C++要手动做内存管理

C++同时提供在堆栈上的自动局部变量,以及从自由存储(free store)分配的对象。对于后者,程序员需手动释放,或使用不同的容器和智能指针。

C++程序员经常进一步优化内存,自定义内存分配策略以提升效能,例如使用对象池、自定义的单向/双向堆栈区等。虽然C++0x还没加入GC功能,但也可以自行编写或使用现成库。

此外,C/C++也可以直接使用操作系统提供的内存相关功能,例如内存映射文件、共享内存等。

这点劳动付出我认为值得,也是一个程序员成长的必由路径。

4、常要重造轮子

我曾参与的C++项目,都会重造不少标准库已提供的功能,此情况在其他语言中较少出现。个中原因分析如下:

  1. C++标准库相对很多语言来说是贫乏的,各开发者便会重复地制造自订库。
  2. C++标准库是用C++编写的(很多其他语言不用自身而是用C/C++去编写库),在能力和性能上,自订库和标准库并无本质差别;
  3. 标准库为通用而设,对不同平台及多种使用需求作取舍,性能上有所影响,例如EA公司就曾发表自制的EASTL规格,描述游戏开发方面对STL的性能及功能需求的特点;
  4. 多个C++库一起使用,经常会因规范不同而引起冲突,又或功能重叠,

所以项目可能须自行开发,或引入其他库的概念或实现(如Boost/TR1/Loki),改写以符合项目规范。

5、C++程序跨平台问题

C++有不错的跨平台能力,但由于直接映射硬件,因性能优化的关系,跨平台能力不及Java及多数脚本语言。然而,实践跨平台的C++软件还是可行的,但须注意以下问题:

  • C++标准没有规定原始数据类型(如int)的大小,需要特定大小的类型时,可自订类型(如int32_t),同时对任何类型使用sizeof()而不假设其大小;
  • 字节序(byte order)按CPU有所不同,特别要注意二进制输入输出、reinterpret_cast法;
  • 原始数据和结构类型的地址对齐有差异;
  • 编译器提供的一些编译器或平台专用扩充指令;
  • 避免作应用二进制接口(application binary interface, ABI)的假设,如调用函数时参数的取值顺序C/C++中没定义,在C++中也不可随便假设RTTI/虚表等实现方式。

总括而言,跨平台C++软件可在头文件中用宏检测编译器和平台,再用宏、typedef、自定平台相关实现等方法去实践跨平台,C++标准不会提供这类帮助。

6、C++缺乏的功能

虽然C++已经非常复杂,相比于其他的语言,仍缺少很多常见的功能,为此C++0x也作出了不少改善。例如:

  • 语言方面加入Lambda函数、闭包、类型推导声明等;
  • 库方面则加入正则表达式、采用哈希表的unordered_set/unordered_map;
  • 引用计数智能指针shared_ptr/weak_ptr等;

C++0x引入多线程的语法和库功能,这是C++演进的一大步;然而,模组、GC、反射机制等在java中熟知的功能虽有提案,却未加进C++0x。

C++的应用

C++并非万能丹,但其应用非常广泛,现总结一下:

  • C++适合构造程序中需求较稳定的部分,需求变化较大的部分可使用脚本语言;
  • 程序须尽量发挥硬件的最高性能,且性能瓶颈在于CPU和内存;
  • 程序须频繁地与操作系统或硬件沟通;
  • 程序必须使用C++框架/库,如大部分游戏引擎,虽然有些C++库提供其他语言的绑定,但通常原生的API性能最好、最新;
  • 项目中某个目标平台只提供C++编译器的支持。

就应用领域来讲,C++适用于开发服务器软件、桌面应用、游戏、实时系统、高性能计算、嵌入式系统、图形处理,网络通讯,界面,数据库等

  • 游戏服务器程序:大型游戏的引擎都是用C或者C++做的,如Unreal/Source 以及中间件,如Havok/FMOD
  • 桌面应用程序:QQ宠物、迅雷、网页浏览器、杀毒软件、卡巴斯基、瑞星等等好多,这些应用软件全部一水的VC++的!
  • 超大型系统系统:比如美国宇航局的程序系统,40多万行C++。
  • 网络底层实现:网络并发通信,网络协议开发,基于串口的远程控制及通信,web后台开发(CGI和ISAPI)
  • 要求运算速度很快的地方:编解码,压缩,嵌入式(嵌入式方面与C语言PK还是存在一些劣势)、加解密算法的实现、图形处理、数据库、高性能计算机等等

 

参考文档

C++强大的背后:http://www.cnblogs.com/miloyip/archive/2010/09/17/behind_cplusplus.html

开发库:http://blog.csdn.net/zhongkeli/article/details/7002464

在此对被参考的文章作者一并致谢!

posted @ 2012-09-20 23:00  百川而粒  阅读(643)  评论(0)    收藏  举报