c++ 性能优化策略
c++ 性能优化策略
作者:D_Guco
来源:CSDN
原文:https://blog.csdn.net/D_Guco/article/details/75729259
1 关于继承:不可否认良好的抽象设计可以让程序更清晰,代码更看起来更好,但是她也是有损失的,在继承体系中子类的创建会调用父类的构造函数,销毁时会调用父类的析构函数,这种消耗会随着继承的深度直线上升,所以不要过度的抽象和继承,更为严重的是当多重继承中并且有虚函数的存在时情况更为复杂,的确,这些问题涉及开销,但是,多重继承减少了编码的负担,同时也让问题的解决方案更加简洁,这当然要付出一些代价.总之,与n个基类的多重继承层次相关的额外虚函数表有n-1个。派生类和最左边的非虚基类共享同一个虚函数表。因此,带有2个基类的多重继承层次,有1个(2-1=1)基类的虚函数表和1个派生类的虚函数表(最左边的基类与派生类共享该虚函数表),总共有2个虚函数表,如果有虚继承的存在,会进一步增长这个过程,它是有额外的开销的。
2 对象的复合:对象的复合和继承很相似,当一个对象包含其他对象构造时也会引起额外的构造。关于这点可能会有很多人不解,认为这是不可避免的,举个例子,比如你的类A中包含了类B非指针和引用对象,那么在你构造对象a的时候会自动调用b的无参构造函数,即使你还没有用到她,用指针代替就没有这种消耗,另外如果你的一个对象中用到数组和字符串,你是选择string和vector还是char* 和c系的数组呢,如果没有用到c++stl库提供的相关的高级用法,建议选择后者。
3 构造函数:尽量用参数列表初始化代替参数,避免值传递初始化。
4 变量延时定义:从c系转过来的仍保留着c的习惯,在函数第一行先把所有用到的变量都定义好,但是c是没有运行时的消耗的,对于c++时不一样的,对于c++对象的构造和销毁时有消耗的,如果有大量的对象只在某个if条件的一个分支中出现,那就会有50%的情况这些消耗是可以避免的。对于这点在一个类中也是一样的,如果成员中有成员只在某个时刻能用,就用指针代替,在构造对象时初始化成空指针,避免构造时调用他的构造函数。
5 虚函数:虚函数的底层实现是通过一个虚函数表来实现的,因此有虚函数的类构造时必须先初始化虚函数表,函数调用时也必须先找到虚函数表,然后通过指针偏移找到相应的函数,通常情况下调用虚函数是没有运行时消耗的,但是根据编译器的实现不同,在调用虚函数时,有些调用可能导致增加虚函数表大小的额外开销,或者只有那些需要调整this指针的调用才会发生额外的运行开销,但不会增加虚函数表的大小,在多重继承和虚基类的时候这种消耗会显著增加,关于继承已经提过,所以避免滥用虚函数和虚继承,有时候可以用模版设计来代替虚继承,把运行时的消耗提前到编译期。关于虚函数的消耗:点击打开链接
6 返回值优化: 虽然c++编译器会选择性的进行RVO优化但是不是强制的,当函数有多个返回语句并且返回不通名称的对象,函数过于复杂,返回对象没有定义拷贝构造函数时,rvo优化是不会执行的,所以当函数返回一个很大的对象时在不确定rvo优化会执行时,尽量避免值传递。
7 变量的定义:在定义变量时尽量避免类型的不匹配造成临时变量的产生。
8 内存管理:c++内存管理的大权由我们自己掌握,对于项目中要频繁申请和释放的对象建议用简单的内存池来管理,可以大大的降低频繁申请和释放内存带来的消耗。
9 善用内联:内联函数不仅仅是简单的函数调用似的优化,他还有一个最大的优点就是,可以让编译期进行进行边界代码的运行环境优化,内联把代码拷贝到执行环境处避免了函数调用带来的消耗,并且编译期可以进行正常的编译优化,而函数调用是不能实现的。
10 stl :记住一点stl不是唯一的选择,有时候也不是最好的选择,合理选择stl善用stl算法。
11 缓存:对于多次使用的计算结果及时缓存,避免重复计算。
12 延时计算:对于不关心计算结果的计算过程尽量延时执行或者异步去执行。
13 多线程:尽可能的使用无锁式多线程开发,锁是一个非常消耗性能的东西,保证数据同步的手段有很多,voalite,原子操作都可已实现,尽量通过一些技巧使用这些手段避免所得使用,如果迫不得已要使用锁,尽量减少锁的消耗,比如降低锁的粒度,使用性能更高的锁等等。
14 std::move操作: 当不得不进行深拷贝时,如果深拷贝数据源在拷贝后就不在使用,尽可能的用move操作代替,或者在参数传递时用move操作代替临时的实参变量。
15 cpu缓存:合理的利用cpu cache可以极大的提高代码的运行效率(例如:数组中以每列遍历和每行遍历的效率的不同),当然多线程环境下也要考虑cpu cache带来的影响。
16 内存对齐:在进行网络编程时,最好对网络中传送的数据快进行内存补齐,通常是8字节对其,提高cpu访问内存效率,从而提高数据读写速度。
17 函数参数:用const引用代替值传递,如果函数参数过多,可以用对象来打包参数,减少参数过多带来的性能消耗。
18 算法: 尽可能的优化你的算法。
19 关于智能指针:对于智能指针我的选择是必须用,它可以大大降低程序的crash频率,但是智能指针的和普通指针相比是有额外的消耗的,她的底层是一个原子操作来来统计引用数和一个普通指针,虽然原子操作和锁相比性能高了不少但是和普通的加减操作还是慢了不少,智能指针的大小为16个字节,而普通指针的大小只有4个字节,拷贝的成本也不一样,所以在使用正确的情况下可以使用智能指针的引用来减少拷贝的消耗(注意这里的前提是正确的使用引用,不要引用以一个即将被销毁的变量)。
20 内存池:对于需要频繁申请和释放的内存对象,如果可以重复利用对象的内存,强烈建议通过内存池或者重载对象的new操作符或者重载对象的placement new操作符来减少频繁的申请和释放内存,从而减少申请和释放内存的消耗和内存碎片的产生。
21 其他优化方案:位运算代替乘除法,前缀运算符代替后缀运算等等。
=============== End
c++ 性能优化策略的更多相关文章
- 常见性能优化策略的总结 good
阅读目录 代码 数据库 缓存 异步 NoSQL JVM调优 多线程与分布式 度量系统(监控.报警.服务依赖管理) 案例一:商家与控制区关系的刷新job 案例二:POI缓存设计与实现 案例三:业务运营后 ...
- 90 % Java 程序员被误导的一个性能优化策略
我们经常看到一些 Java 性能优化的书或者理念,说不要在循环内定义变量,这样会占用过多的内存影响性能,而要在循环外面定义.接触 Java 这么久以来,相信很多 Java 程序员都被这种代码性能优化策 ...
- 在 Android开发中,性能优化策略十分重要
在 Android开发中,性能优化策略十分重要本文主要讲解性能优化中的布局优化,希望你们会喜欢.目录 示意图 1. 影响的性能 布局性能的好坏 主要影响 :Android应用中的页面显示速度 2. 如 ...
- 52 条 SQL 语句性能优化策略,建议收藏
本文会提到 52 条 SQL 语句性能优化策略. 1.对查询进行优化,应尽量避免全表扫描,首先应考虑在where及order by涉及的列上建立索引. 2.应尽量避免在where子句中对字段进行nul ...
- HBase最佳实践-写性能优化策略
本篇文章来说道说道如何诊断HBase写数据的异常问题以及优化写性能.和读相比,HBase写数据流程倒是显得很简单:数据先顺序写入HLog,再写入对应的缓存Memstore,当Memstore中数据大小 ...
- Web前端性能优化策略
前端性能优化需要从前端的资源类型分析,以减少请求资源和请求时间为目的.目前的类型包括图片.javascript.css.动态数据等,不同的资源对于运算.带宽等的依赖也不同,因此优化的方式也不同.参照以 ...
- MIC性能优化策略
MIC性能优化主要包括系统级和内核级:系统级优化包括节点之间,CPU与MIC之间的负载均衡优化:MIC内存空间优化:计算与IO并行优化:IO与IO并行优化:数据传递优化:网络性能优化:硬盘性能优化等. ...
- HBase最佳实践-读性能优化策略
任何系统都会有各种各样的问题,有些是系统本身设计问题,有些却是使用姿势问题.HBase也一样,在真实生产线上大家或多或少都会遇到很多问题,有些是HBase还需要完善的,有些是我们确实对它了解太少.总结 ...
- ElasticSearch性能优化策略【转】
ElasticSearch性能优化主要分为4个方面的优化. 一.服务器部署 二.服务器配置 三.数据结构优化 四.运行期优化 一.服务器部署 1.增加1-2台服务器,用于负载均衡节点 elasticS ...
随机推荐
- PIMPL(private implementantion)模式(转载)
前记:请搜索PIMPL(private implementantion)模式和桥接模式, PIMPL是桥接模式的一种典型实现 以下转自:http://blog.csdn.net/nrc_douning ...
- 前端知识点回顾——Javascript篇(四)
Symbol 为什么需要symbol ES5里面对象的属性名都是字符串,如果你需要使用一个别人提供的对象,你对这个对象有哪些属性也不是很清楚,但又想为这个对象新增一些属性,那么你新增的属性名就很可能和 ...
- nginx 反向代理实现负载均衡*理论
Nginx负载均衡集群介绍 负载均衡集群提供了一种廉价,有效,透明的方法,来扩展网络设备和服务器的负载,带宽和吞吐量,同时加强了网络数据处理能力,提高了网络的灵活性和可用性. 搭建负载均衡服务的需求: ...
- 一个Action中,可以写多个类似的业务控制方法
1)通过模块根路径 + 功能子路径 = 访问模块下子功能的路径 @Controller @RequestMapping(value="/user") public class Us ...
- 传统Web应用请求和响应特点【显示当前时间】
(1)请求:浏览器以HTTP协议的方式提交请求到服务器 (2)响应:服务器以HTTP协议的方式响应内容到浏览器 注意:HTTP是WEB大众化非安全协议 HTTPS是WEB安全协议,是基于HTTP协议的 ...
- 配置了configuration.xml之后提示找不到映射关系
在启动类里面单独增加一个Bean即可解决 @Bean public DatabaseIdProvider getDatabaseIdProvider(){ DatabaseIdProvider dat ...
- iscsi序列一、搭建iscsi存储系统
一.NAS和SAN服务器概述 SAS: 容量小, 300G, 600G, 900G, 价格贵. SATA:容量大,500G, 750G, 1T, 2T, 3T, 4T 不支持热插拔,价格低. 假S ...
- python+Selenium PhantomJS网页截图
PhantomJS是一个基于webkit的JavaScript API.它使用QtWebKit作为它核心浏览器的功能,使用webkit来编译解释执行JavaScript代码.任何你可以在基于webki ...
- Email功能的设定
在前期制定发送邮件功能时,都是使用导入import smtplib模块来实现,虽说能实现, 但是对新人.刚接触的来说不太友好,虽然网上五花八门的教程一大推,但还是要自己花不少时间才搞定(笔者就是) 在 ...
- 并发-synchronized
线程并发-synchronized和Lock简单认知 前几天刚加深了线程的了解,期间在验证各种方法及多线程时遇到一些疑问,在高并发的情况下,怎么做才能保证程序还能按照我们预期的正常运行下去,这就是我们 ...