C++性能优化(一)——应用程序性能优化简介_c++cpu问题分析-程序员宅基地

技术标签: c++  性能优化  

、程序性能优化简介

1、程序性能优化简介

在计算机发展的早期阶段,硬件资源相对而言是非常昂贵的,CPU运行时间与内存容量给程序开发人员设置了极大限制。因此,早期的程序对运行性能和内存空间占用的要求是非常严格的,很多开发人员为了减少1%的CPU运行时间,为减少几十个甚至几个字节而不懈努力。随着计算机技术的快速发展,硬件资源变得相对便宜。但如果认为软件开发时,程序的性能优化不再重要,硬件将解决性能问题也是片面的。计算机硬件的发展解决了部分软件的性能问题,但随着硬件计算能力的提高,用户对软件功能的要求也越来越高,软件功能也变得越来越复杂,给用户的界面和操作体验也越来越智能和友好。但复杂的用户需求带来软件性能上的要求是硬件不能完全解决的。众多实际项目经验证明,如果在开发软件时不重视性能优化,最终实现了软件的功能要求,但软件的运行效率低下,最终也不能给用户带来很好的效益。但另一方面,计算机硬件越来越便宜,而优秀的软件开发工程师则越来越昂贵,在软件开发过程中无限制的性能优化同样会导致软件开发过程中人力成本的大幅增加。因此,软件开发过程中的性能优化必须在便宜的计算机硬件和昂贵的优秀工程师之间找到一个平衡点。

2、程序性能优化的流程

应用程序性能优化的流程如下:

(1)性能测量,对于规模较大、较为复杂的软件系统,测量性能数据是进行性能优化的基础。只有获取真实的数据才能分析数据找出系统的性能瓶颈。

(2)分析数据,找到系统的性能瓶颈。性能瓶颈必须建立在客观真实的性能数据基础上,不能是主观臆测的。

(3)分析原因,修改程序,是程序性能优化的核心。程序的性能包括启动速度、运行速度、运行时占用内存等。影响程序性能的因素主要分为两类:

(1)软件编程设计因素:算法和数据结构的选择,编程语言的使用。

(2)软件系统结构因素:动态库、静态库的组织,外部数据的存储以及网络环境等。

软件编程设计因素是对软件性能影响较大的因素,只有对算法、数据结构、编程语言有深入的了解才能分析出原因,并且找到解决性能问题的方法。

软件系统结构因素通常与操作系统紧密相关。对于现代软件,由于功能复杂,通常采用组件形式,以最大限度的提高可复用性。因此,一般会包含一些动态库、静态库,库文件的组织也会影响到软件系统的性能。

、程序性能的定义

1、性能指标定义

应用程序的性能指标通常是多维的,比如响应时间、并发量等。对于桌面应用程序,其服务对象通常为终端用户。因此,桌面应用程序最重要的性能指标是响应时间,即针对某一个具体的操作,用户从发出命令到应用程序完成任务并响应用户的时间,响应时间越短越好。

除了响应时间,内存使用也是桌面应用程序的重要指标之一。内存使用包括进程工作集(任务管理器看到的内存使用)和虚拟内存使用两个指标,越小越好。如果一个应用程序占用内存过高,会影响其它正在运行的应用程序的响应时间。

根据可用性设计,桌面应用程序的设计原则如下:

(1)小于0.1秒的响应时间,用户感觉是即时的。

(2)小于1秒的响应时间,用户感觉是可接受的。

(3)大于1秒的操作应该有一个简单标示(如鼠标变成沙漏)。

(4)大于10秒的操作应该有明显的提示(如进度条)。

2、性能基准

桌面应用程序的性能指标包括响应时间和内存使用,但响应时间和内存使用指标通常针对单个操作。现代软件系统通常包括多项功能,例如一个文字处理软件能够提供的功能不下数百种,每种功能作用在不同类型和大小的文档上会表现出不同的性能,性能基准就是用于定义程序的总体性能的。

性能基准(Performance Benchmark)是用来衡量应用程序整体性能的一套体系,通过为应用程序输入预先设计好的工作负载,运行一批基准用例,运行结果可以反映应用程序在通常情况下的性能。因此,性能基准=基准负载+基准用例。

(1)基准负载

对于桌面应用程序,运行性能基准时需要的基准负载通常表现为一系列基准文件。基准文件应该是具有典型大小和典型内容的文件,而基准文件选取的优劣直接影响性能基准的准确性。

对于通用文字处理软件,主要功能是创建、打开文档,修改并保存文档,支持的文档类型包括.doc,.dot,.odt,.ott,.txt,.lwp等,支持文字、图片、文本框、表格、图形等。设计基准文件时,从文档类型考虑,在兼顾到主要的文档类型又要排除类似的文档类型;从文档内容考虑,需要覆盖用户最常用的内容对象类型和文档大小,具体基准文件列表如下:

名字

内容

大小(KB)

类型

复杂文档100.doc

100页,100图片,16表格,60文本框,其它

3082

doc

复杂文档100.odt

100页,100图片,16表格,60文本框,其它

1249

odt

复杂文档100.lwp

100页,100图片,16表格,60文本框,其它

1246

lwp

简单文档120.doc

120页,纯文本

672

doc

简单文档120.odt

120页,纯文本

19

odt

简单文档120.lwp

120页,纯文本

13

lwp

对于同一种文档类型,每一种文档类型包含两个基准文件,分别有不同的文档内容。

(2)基准用例

基准用例是性能基准测试时需要执行的一系列用例。基准用例的选择有一定原则,既要尽可能全面地覆盖应用程序的主要功能,又不能像功能测试用例那样复杂,因此,基准用例应该是用户日常操作经常遇到的情形。

不同的基准用例在性能基准中的地位并不相同,每一个基准用例都需要一个权值来表明它对整体性能基准的贡献度。权值的定义依据具体情况各有不同,一个比较实用的定义公式如下:

权值=用例频率X用例重要性

用例频率是用户一定时间内执行该用例的平均次数。理想的用例频率应该通过用户行为数据反馈获得。例如通用文字处理软件的用户一天内可能会执行“打开文档”用例5次,执行“保存文档”的用例15次。

用例重要性是一个修正系数,反映用例没有完成前对用户工作的影响程度。文字处理软件打开一个文档时有“异步打开”的功能,即程序会首先读入文档的部分内容并显示给用户,然后在后台继续读入文档的后续内容。对于“异步打开”功能可以定义两个用例,“第一页显示”(从用户选择打开文档到文档的第一页显示出来的过程)和“全部读入完毕”(从用户选择打开文档到文档的所有页的内容已经加载完毕的过程)。“第一页显示”用例的重要性为1,表示不执行完本用例,用户不能继续工作;“全部读入完毕”用例的重要性为0.5,表示本用例不会显著影响用户的工作,文档在后台加载,用户前台已经可以编辑,除非用户需要编辑的内容还没有加载出来。

文字处理程序的部分基准用例如下:

名字

描述

频率

重要性

权值

冷启动

操作系统重新启动后应用程序第一次启动的过程

1

1

1

热启动

应用程序再次启动的过程

6

1

6

关闭

从用户关闭到程序完全退出的过程

7

0.2

1.4

新建文档

新建文档到输入光标闪动的过程

3

1

2

第一页显示(简单doc文档)

从用户选择文档打开到第一页显示并可编辑的过程

5

1

5

全部读入完毕(简单doc文档)

从用户选择文档打开到文档所有页的内容全部加载的过程

5

0.5

2.5

保存文档(简单doc文档)

用户插入一个字符,从保存开始到保存结束的过程

15

1

15

第一页显示(复杂doc文档)

从用户选择文档打开到第一页显示并可编辑的过程

5

1

5

全部读入完毕(复杂doc文档)

从用户选择文档打开到文档所有页的内容全部加载的过程

5

0.5

2.5

保存文档(复杂doc文档)

用户插入一个字符,从保存开始到保存结束的过程

15

1

15

插入图片

在第一段插入特定图片的过程

10

1

10

翻页

从第一页翻到第二页的过程

100

1

100

粘贴

复制最后一个段落粘贴到第一个段落

50

1

50

打印预览

打印预览整篇文档的过程

5

1

5

查找

从查找特定字符开始到找到的过程

20

1

20

相同的操作步骤操作不同类型或不同内容的基准文件会形成不同的基准用例。

3、性能基准的运行

准备好基准文件和基准用例后就可以运行性能基准并得出基准结果。

为了保证性能基准运行的准确性,性能基准的测试环境必须满足一定要求。例如保证固定的基准测试平台(软件和硬件平台不变),尽可能排除其它应用程序对目标应用层程序的影响。基准测试平台也可以有同时运行在多种硬件平台上的考量:运行在4G内存和8G内存时应用程序的性能表现的差别;运行在三年前硬件配置和当前主流硬件配置的性能表现的差别。

运行基准测试的过程是在固定的基准测试环境中针对基准文件顺序执行一系列基准用例并记录下每个用例结果的过程,执行过程分为手动执行和自动执行,结果记录也可以分为手动记录和自动记录。

通常手工执行和记录是基础,最能反映最终用户的体验。

自动运行和记录是目标,可以大幅提升工作效率,并排除人工不稳定的结果。但自动运行的脚本必须保证多次自动运行结果的稳定,保证自动运行结果和手动运行结果的可比较。

性能基准运行的过程需要注意:

(1)每一个用例需要运行多次求平均值,如需要去除最大值、最小值,然后取平均值。

(2)多个用例执行的先后顺序必须固定,否则很难得到稳定的性能基准结果。

4、性能基准结果

性能基准运行结果的原始数据是一系列的绝对数值,可以根据不同的需要生成不同的报告,如:

整体性能水平分值:每个用例绝对值结合每个用例的权值,可以给整体性能水平打分。

性能变化趋势图:历史上不同版本的整体性能分值曲线可以体现出性能变化趋势。

关键性能指标图表:给用户演示的重点用例的结果图表。

产品性能对比图:和其它产品的性能对比图,包括绝对值的对比和加权后分值的对比。

文字处理程序的部分基准用例运行结果数据如下:

名字

结果值(秒)

权值

分值

冷启动

10.5

1

10.5

热启动

2.1

6

12.6

关闭

2.3

1.4

3.22

新建文档

0.8

3

2.4

第一页显示(简单doc文档)

0.5

5

2.5

全部读入完毕(简单doc文档)

2

2.5

5

保存文档(简单doc文档)

0.2

15

3

第一页显示(复杂doc文档)

0.8

5

4

全部读入完毕(复杂doc文档)

4.8

2.5

12

保存文档(复杂doc文档)

0.8

15

12

插入图片

0.1

10

1

翻页

0.02

100

2

粘贴

0.03

50

1.5

打印预览

0.8

5

4

查找

0.01

20

0.2

总分

71.51

性能基准可以反映应用程序的总体性能,定义良好的性能基准用途如下:

(1)应用程序性能的绝对指标。任何想要了解产品性能的人,无论是管理层还是客户,都可以通过产品性能报告了解产品的性能。

(2)通过比较不同版本的基准结果,提前发现性能下降的问题和验证性能提升的设计结果。软件开发过程中通常都会进行每日构建,性能基准也可以在每日构建的基础上每日运行,及时发现性能问题,而不是在产品即将发布时进行性能优化。

(3)比较不同厂商的类似软件的性能。横向的比较需要性能基准,可以找出自己软件产品的性能薄弱环节,集中力量进行优化。

、程序性能分析方法

1、性能分析方法简介

拥有定义良好的性能基准后,可以轻易发现应用程序存在的性能问题。发现性能问题后需要对性能问题进行分析,程序的性能分析过程包括:性能问题分类、查找性能瓶颈、进行性能优化。

2、性能问题分类

一个操作执行太慢,需要首先分类是IO操作密集引起的问题还是CPU相关的计算密集型问题。正确的分类将直接影响进一步的问题分析。

区别IO相关还是CPU相关问题的简单方法是隔离IO影响后,看性能是否得到改善,例如同时在机械硬盘和SSD硬盘上测试,如果性能显著提高,则是IO相关的问题。

对于文字处理软件,冷启动需要10.5秒,热启动需要2.1秒,因此冷启动的主要问题在IO。无论是冷启动还是热启动,应用程序都是完全退出后再重新启动,执行的代码流程完全一样,唯一区别在于IO:冷启动后操作系统会缓存很多动态库的代码页在内存。

3、查找性能瓶颈

对性能问题分类后,可以使用性能分析工具在代码层次查找性能瓶颈,性能分析工具有监测工具和注入工具两类。

监测工具如下:

perfmon,Windows工具,可以监测所有的性能指标。

FileMon,Windows工具,监测IO操作。

ProcessExplorer,Windows工具,监测进程相关的所有操作。

sysstat,Linux工具,监测所有的性能指标。

iostat,Linux工具,监测IO操作。

vmstat,Linux工具,监测内存变化。

注入工具如下:

IBM rational quantify,Windows工具,针对C++应用程序代码注入,可以计算函数调用次数、时间等。

Valgrind,Linux工具,针对C++应用程序代码注入,可以计算函数调用次数、事件、内存分配、内存泄漏检测等。

IBM rational purify,Windows工具,针对C++应用程序代码注入,可以进行内存分析。

WinDbg,Windows工具,调试工具。

GDB,Linux工具,调试工具。

Dependency walker,Windows工具,分析动态链接库之间的动态、静态依赖关系。

ldd,Linux工具,分析共享对象间的依赖关系。

4、查找性能优化机会

代码层次的性能优化设计的改动通常局限在有限的函数调用内,相对比较容易完成。进一步的性能提升的机会需要在设计层次进行查找。设计层面的性能分析需要性能优化者对软件的整体架构有比较深入的了解,需要具体问题具体分析。

四、程序性能优化方法

性能问题分析完成后,需要进行性能优化。根据性能分析结果的不同,优化方法也各有不同。

1、针对IO瓶颈的性能优化

每次IO操作大概在10ms量级,100次就需要1秒左右,因此尽量避免不必要的IO操作。具体做法如下:

(1)预先顺序读文件避免随机访问。

(2)合并多个小文件为单个大文件。

(3)优化动态库文件的加载。

(4)交错IO时间和CPU时间。

2、针对计算密集的性优化

计算密集的性能问题主要有内存分配性能、字符串操作、共享变量的互斥锁保护等,具体优化方法如下:

(1)去除冗余代码。

(2)字符串操作优化。

(3)减少内存分配、释放操作,例如使用内存池。

(4)减少不必要的互斥锁操作。

(5)根据性能需求选择数据结构。

(6)延迟工作,按需执行。

(7)减少跨进程的调用。

(8)使用高性能的函数库。

3、C++语言特性相关的性能优化

C++语言特性相关的性能优化包括内联函数、引用、编译优化选项等。

4、用户体验的性能优化

有些设计不能真正提升性能,但让用户体验到了性能提升。如:

(1)流式播放设计,用户不需要等到视频文件下载完成再播放,可以边下载边播放。

(2)线程化设计,对于需要较长时间完成的操作,可以设计为非阻塞式的,用户可以在等待时间完成其它操作任务。

5、设计层面的性能优化

设计层面的性能优化需要根据软件整体架构具体问题具体分析。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/A642960662/article/details/123029121

智能推荐

udk开发-稀里糊涂_networkinterfaceidentifierprotocol-程序员宅基地

文章浏览阅读1.4k次。在此情况下,DXE Runtime Driver必须创建一个signal类型的Event,当SetVirtualAddressMap() 被OS调用的时候,该Event将被通知。​ DXE Runtime Driver创建的signal类型的Event所用到的通知函数不允许直接或者间接使用UEFI Boot Services、**UEFI Console Services **或者 UEFI Protocol Services。所有的Set或者Get的值在boot time memory关闭后将会丢失。_networkinterfaceidentifierprotocol

c语言中struct和typedef struct的用法_typedef struct用法-程序员宅基地

文章浏览阅读2.2k次,点赞18次,收藏51次。基本形式在C语言中,可以使用结构体(Struct)来存放一组不同类型的数据。结构体的定义形式为:struct 结构体名{ 结构体所包含的变量或数组};结构体是一种集合,它里面包含了多个变量或数组,它们的类型可以相同,也可以不同,每个这样的变量或数组都称为结构体的成员(Member),比如????struct stu{ char *name; //姓名 int num; //学号 int age; //年龄 char group; //所在学习小组_typedef struct用法

用 .NET 启动你的 DJI Ryze Tello 无人机_c# 大疆sdk-程序员宅基地

文章浏览阅读2.2k次,点赞5次,收藏6次。用 .NET 启动你的无人机_c# 大疆sdk

基础的Linux命令_touch index.js-程序员宅基地

文章浏览阅读92次。基本的Linux命令改变目录回退到上一个目录显示当前所在目录路径列出当前目录中的所有文件新建一个文件,如index.js,在当前目录下新建一个index.js文件删除一个文件新建一个目录(新建一个文件夹)删除一个文件夹index移动文件重新初始化终端清屏查看命令历史帮助退出注释改变目录cd回退到上一个目录cd…显示当前所在目录路径pwd列出当前目录中的所有文件ls新建一个文件,如index.js,在当前目录下新建一个index.js文件touch index.js删除一个文件如rm _touch index.js

Qt中如何将QComboBox中的选项StringItem与数值内联binding_qt combobox显示数值和实际值怎么绑定-程序员宅基地

文章浏览阅读501次。Qt中如何将QComboBox中的选项StringItem与数值内联binding开发文档中有两种方法第一种:第二种:这里介绍第二种(我认为更简单的一种)就用我目前做的一个小项目来说吧我的combo box中有各种各样的运动,每种运动自动内联着它所对应的一个小时所消耗的卡路里(int)consume::consume(QWidget *parent) : QDialog(parent), ui(new Ui::consume){ ui->setupUi(_qt combobox显示数值和实际值怎么绑定

最新大猿人中控充值系统 免授权学习版 支持公众号H5、分销等功能_猿人充值系统 3.2 漏洞-程序员宅基地

文章浏览阅读1.5k次。简介:最新大猿人中控充值系统 免授权破解版 支持公众号H5、分销等功能功能简介:大猿人中控系统目前是市面上用的最多的电话费充值中控系统,支持代理分销、公众号H5、API接口对接等功能,也是目前最完善的一款中控系统,前端全开源,已破解免授权!配置环境:php7.3 + Redis搭建教程:1、首先吧大猿人中控系统压缩包上传到服务器内进行解压,然后吧数据库文件导入数据库内2、修改/application/database.php 文件进行配置链接数据库。_猿人充值系统 3.2 漏洞

随便推点

ADC参数详解_adc电流电压零漂值-程序员宅基地

文章浏览阅读9.6k次,点赞9次,收藏117次。特性或指标总述本文将从以下特性进行简单的叙述。结合了《ADC设计基础》和TI的一些教学视频。分辨率转换误差转换速度采样率奈奎斯特采样准则混叠和抗混叠滤波器DNLINL热噪声谐波失真THDSNRENOBSFDRIMD孔径抖动孔径延迟奈奎斯特区补充分辨率一般ADC都说注明是8bit,16bit或者是24bit。这里的数值也就是分辨率的意思。分辨率是衡量A..._adc电流电压零漂值

服务器阵列卡缓存显示错误,服务器阵列卡(缓存)-程序员宅基地

文章浏览阅读1.1k次。RAID卡介绍:提到RAID卡就不得不提到什么是RAID。RAID是英文Redundant Array of Independent Disks的缩写,翻译成中文即为独立磁盘冗余阵列,或简称磁盘阵列。简单的说,RAID是一种把多块独立的硬盘(物理硬盘)按不同方式组合起来形成一个硬盘组(逻辑硬盘),从而提供比单个硬盘更高的存储性能和提供数据冗余的技术。组成磁盘阵列的不同方式成为RAID级别(RAID..._把raid缓存强制开启 显示参数无效

您绝对不能错过的 10 个 OKR 示例!_优秀的okr案例-程序员宅基地

文章浏览阅读429次,点赞6次,收藏8次。在此基础上,制定团队 OKR,它可以是产品层面的或部门层面的,但它们会融入组织的目标中。使用 OKR 方法的一个巨大好处是,它可以针对不同的部门和团队进行细分, 以便整个公司追求相同的组织目标,但利用特定的关键结果。如果您没有达到 100% 的关键结果,您仍然应该为实现这一目标所付出的努力感到自豪,评估是否需要进行更改,并重新调整下一个周期的目标和关键结果。令人惊讶的是,伦敦商学院进行的一项研究显示,在接受调查的 11,000 名高级管理人员中,只有三分之一能够列出他们公司的三大优先事项。_优秀的okr案例

HDU 5350(MZL's munhaff function-哈夫曼树)_禎痲霤攷 hdu-程序员宅基地

文章浏览阅读2.1k次。MZL's munhaff functionTime Limit: 3000/1500 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 230 Accepted Submission(s): 133Problem DescriptionMZL is _禎痲霤攷 hdu

AndroidStudio4.1 自定义模板_android studio 4.1 自定义模板-程序员宅基地

文章浏览阅读1.3k次。AndroidStudio4.0之前,可以在template的文件夹里使用freemarker的自定义模板,可以在AndroidStudio的文件夹中,随意的添加适合自己的自定义模板,之前鸿洋大神的文章已经有来详细的介绍(https://blog.csdn.net/lmj623565791/article/details/51592043)。但是从4.1版本开始提供新的方式,Geminio,用Kotlin的形式编写新的template,而且需要使用插件的形式,才能使用自定义的模板,摸索了好几天,终于解决了_android studio 4.1 自定义模板

微信小程序云开发-酒店点餐类系统,附带(node.js在widows环境下的配置过程)_云开发可以做扫码类么-程序员宅基地

文章浏览阅读3.2k次,点赞3次,收藏11次。前些日子,帮一个学生做了一个毕业设计,是关于酒店点餐的微信小程序,现在整理一下过程。本款小程序是基于微信云开发的,现在做微信小程序的一大方便是:微信给大家提供了免费空间(云开发),对于不想花钱去租用服务器和域名的小伙伴儿来说,这无疑是一大喜事! 本款小程序非常适合商城类小程序的二次开发或是学习商城类小程序最佳的一个案例。废话不多说,直接上图:小程序..._云开发可以做扫码类么

推荐文章

热门文章

相关标签