您的位置:首页 > 编程语言 > C语言/C++

C++并发编程性能优化

2017-11-26 14:45 295 查看
C++并发编程性能优化

笔者使用C++语言进行软件开发。最近的两年时间做了一些关于软件系统的性能优化方面的工作。总结了一些性能优化,尤其是并发方面的性能优化的可参考的思路。分类总结如下,可以作为关于这方面的参考。

应用程序的性能要求,一般主要分类为:CPU消耗型,内存消耗型,磁盘消耗型,网络消耗型。

做性能优化,可以从如下的思路入手,
(1)语言方面。

    语言方面包括语言的特性,语言的升级。主要指的是利用语言的语法规则,进行性能优化。

    就C++语言来讲,有如下特性可以利用:

    第一点可以利用引用或指针,来减少类的构造和析构。虽然说现在的CPU已经快的不行,但是频繁大量的构造和析构,往往有时候是在做无用功,本可以避免。构造析构不仅只是对象的创建和销毁,对于参数还要进行入栈出栈。如果对象含有内存、句柄等等的资源,那么对于资源的获取、访问与销毁,就要精心构造你的copy-constructor和operator=,否则就会引起内存问题。

    在C++98/03标准里,有左值引用可以利用来进行优化。

    在C++11标准里,引入了右值引用、move语义和forward完美转发的新特性,这些新特性的引入,主要的就是为了进行性能优化。

    随着C++11新特性的引入,早期C++的类的4大函数(即constructor,destructor,copy-constructor,operator=),也扩展编程了6大函数(新增的为带右值引用的copy-constructor和operator=)。

    

    第二点可以利用语言提供的原子操作,部分地代替锁来进行互斥。但是是否能够进行原子操作要依据它的规则。

    
(2)I/O方面。

    工作原因,笔者所经历的I/O方面的优化,主要集中在网络I/O上,网络I/O又主要是针对TCP进行的优化。TCP的传输优化,可以从互联网上找到非常多的资料,无外乎3个思路,使用异步I/O模型,修改TCP选项,使用更优的拥塞控制算法。
笔者之前给公司的一台java开发的媒体服务器做性能优化,应用协议是http,主要是想提高tps。该视频服务软件是第三方公司提供,我们使用它的sdk做二次开发,优化的方法是修改tcp选项。优化后,该sdk的tps从400~500,提高到1000以上。
关于tcp的拥塞控制算法,目前笔者所使用的较新的算法是google公司基于大数据统计而改进的BBR算法。
针对传输层的优化不一而足,除了上面提到的3个常规思路外,必要情况下,也可以考虑更换传输层协议。笔者所在团队之前做一款针对家用的监控摄像机时,曾考虑过使用tcp/udp之外的传输协议进行技术预研,后来由于公司政策方面一些原因没有推动落地。

(3)架构方面。
架构方面,引起并发性能的限制,可以说是最不容易进行重构优化的。因为架构的变动会引起连锁反应,除了耦合模块的修改外,功能测试、产品发布等都是需要提前做好沟通和会议安排的。笔者团队此前曾就一款C++开发的视频服务器做优化,也是针对http做tps优化,通过对架构进行调整,并附带有数据结构和锁的优化,tps从1000优化到7000。网络是千兆单网卡,7000tps当时是把带宽占用满了,基本也就接近于网络的负载极限。

架构方面的优化手段,诸如对内存数据库的使用,内存池的使用优化,线程池的使用和优化,等等。另外比较隐蔽的架构优化,包括数据结构的优化,业务模型的合理设计,等等。

(4)库方面。
库方面,其实主要说的就是开源库的选择。目前有一定热度、有名的开源库,基本都能够保证较为不错的性能。

作为一名C++开发者,笔者的最深体会是,C++是最容易引起开发者重新造轮子的语言。类型声明不一致,头疼;编码风格不一样,头疼;借口声明不统一,头疼;没有强大的基础库,有各种各样实现同样目的库,头疼......C++就是这样,要么是没有选择的痛苦,要么是选项太多的痛苦。

(5)业务和资源整合方面。
业务和资源整合方面的优化,其实并没有什么固定方法可以借鉴,因为业务是强依赖与开发者的思维方式和使用习惯的,业务也往往是用户、甲方的使用者提出来的。一般来讲,业务与资源整合往往会影响代码逻辑。这通常包括,
要尽量减小互斥锁的代码范围。范围越大,竞争条件在时间维度就越激烈。
避免死锁。
对于较少set、更多时候是get的变量,可使用读写锁。
使用条件变量减少频繁的轮训询问。
减少内存拷贝。(这一条也可归于I/O方面。)

进行软件性能优化的思路手段很多,绝对不可能一言以蔽之。具体的方法还需要开发人员多思考,多借鉴,多学习优秀经验。

下面对文章内提到的优化点进行汇总:

1、减小锁范围

2、避免死锁

3、使用读写锁

4、使用条件变量

5、使用原子操作

6、使用线程池

7、精心设计你的数据结构

8、使用内存池

9、减少内存拷贝

10、对你的业务流程进行优化

11、使用内存数据库

12、使用引用和指针代替值传参

13、减少对象的构造和析构次数

14、选择优秀的库

15、tcp优化,拥塞算法,NODELAY等

16、使用右值引用

17、优化你的领域模型
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: