`
ribishuangba
  • 浏览: 292738 次
文章分类
社区版块
存档分类
最新评论

十三性能优化

 
阅读更多
<meta content="text/html; charset=utf-8" http-equiv="CONTENT-TYPE"> <meta content="OpenOffice.org 2.2 (Linux)" name="GENERATOR"> <meta content="freebird" name="AUTHOR"> <meta content="20070510;9550000" name="CREATED"> <meta content="root" name="CHANGEDBY"> <meta content="20070717;14010300" name="CHANGED"> <style type="text/css"> <!-- @page { size: 8.5in 11in; margin: 0.79in } P { margin-bottom: 0.08in; line-height: 0.1in } H1 { margin-top: 0.24in; margin-bottom: 0.23in; line-height: 200%; page-break-inside: avoid } H1.western { font-family: "Liberation Serif", serif; font-size: 22pt } H1.cjk { font-family: "DejaVu Sans"; font-size: 22pt } H1.ctl { font-family: "DejaVu Sans"; font-size: 22pt } H2 { margin-top: 0.18in; margin-bottom: 0.18in; line-height: 173%; page-break-inside: avoid } H2.western { font-family: "Cambria", serif; font-size: 16pt } H2.cjk { font-family: "宋体", "SimSun"; font-size: 16pt } H2.ctl { font-family: "Times New Roman", serif; font-size: 16pt } --> </style>

性能优化

Linux下程序性能分析工具gprof

gprof 安装在Linux 系统的 /usr/bin 目录下. 它能剖析你的程序,并分析出程序的哪一个部分在执行时最费时间.

gprof 将告诉你程序里每个函数被调用的次数和每个函数执行时所占时间的百分比. 你如 果想提高你的程序性能的话这些信息非常有用.

为了在你的程序上使用 gprof, 你必须在编译程序时加上 -pg 选项. 这将使程序在每次 执行时产生一个叫 gmon.out 的文件. gprof 用这个文件产生剖析信息.在你运行了你的程序并产生了 gmon.out 文件后你能用下面的命令获得剖析信息:

gprof <program_name>

参数 program_name 是产生 gmon.out 文件的程序的名字. 为了说明问题,在程序中增加了函数count_sum()以消耗CPU时间,程序如下

#include <stdio.h>

static void my_print (char *);

static void my_print2 (char *);


main ()

{

char my_string[] = "hello world!";

my_print (my_string);

my_print2 (my_string);

my_print (my_string);

}


void count_sum()

{

int i,sum=0;

for(i=0; i<1000000; i++)

sum += i;

}


void my_print (char *string)

{

count_sum();

printf ("The string is %s ", string);

}

void my_print2 (char *string)

{

char *string2;

int size, i,sum =0;

count_sum();

size = strlen (string);

string2 = (char *) malloc (size + 1);

for (i = 0; i < size; i++) string2[size -1 - i] = string[i];

string2[size] = '';

for(i=0; i<5000000; i++)

sum += i;

printf ("The string printed backward is %s ", string2);

}



$ gcc -pg -o hello hello.c

$ ./hello

$ gprof hello | more

将产生以下的输出

Flat profile:

Each sample counts as 0.01 seconds.

% cumulative self self total time seconds seconds calls us/call us/call name

69.23 0.09 0.09 1 90000.00 103333.33 my_print2

30.77 0.13 0.04 3 13333.33 13333.33 count_sum

0.00 0.13 0.00 2 0.00 13333.33 my_print


由以上数据可以看出,执行my_print()函数本身没花费什么时间,但是它又调用了

count_sum()函数,所以累计秒数为0.13.

技巧: gprof 产生的剖析数据很大, 如果你想检查这些数据的话最好把输出重定向到一个 文件里。

.

影响软件效率的因素


软件性能由两大因素决定,如上图。软件设计是语言无关的,设计者必须充分了解软件的主题功能,设计不良造成的性能问题不要指望通过编写代码解决。编码对于性能也是有影响的,比如你不应该将常量表达式放入循环中,这样会增加计算次数。

软件设计中对性能的影响又包含两个因素,一个是算法和数据结构,一个是程序分解。从技术观点来看,一个程序就是一个算法,不过通常术语“算法和数据结构”指的是查找、排序、访问、压缩以及操作大型的数据集合。算法和数据结构对程序的性能同常有影响,但并不是唯一的因素。程序分解包含了将一个完整的大任务分解成一系列相互关联的子任务、对象体系结构、函数、数据和业务流。

编码对性能的影响也可以分成四个子因素,如上图。

C++对C做了补充和完善,但是有些C++的构件对性能作出了一定的牺牲,这是语言的因素。

当前的不少操作系统设计会让你感觉内存似乎不会用完,可以并行执行,CPU专门为自己的程序服务,统一的内存访问模式,但是实际上即便是采用虚拟内存设计的操作系统,内存也会有用完的时候;CPU不可能总是执行你的程序,而是所有程序轮流使用CPU,每次获得一定的时间片来执行;内存访问模式不是统一的,访问硬盘和内存以及高速缓存都是不一样的,因此性能也不一样;在一个单CPU的机器上,并行执行往往不能带来好处,可能还会导致程序运行速度变慢。

不同的库提供了相同的函数,但是性能表现不一定相同,比如sprintf和itoa。

编译器优化完全取决于编译器实现厂商,因此差异很大。

编写高性能代码的建议

以性能为名,将设计或代码变得更加复杂,从而导致可读性更差,但是并没有经过验证的性能需求(比如实际的度量数据和与目标的比较结果)作为正当理由,因此本质上对程序并没有好处。

首先,应该关注代码尽可能的清晰易读,清晰的代码更容易优化。先让程序做正确的事情,然后再让它更快速应该较容易。

但是要掌握一些惯用技巧,比如优先使用前缀形式的++,--操作,传递引用,延迟定义变量,使用初始化列表初始化成员变量。

不要过早的使用内联,应该通过工具分析哪些函数真正需要内联。

当真正需要优化性能的时候,首先使用现代性能分析工具找出程序中的主要瓶颈。

但是作为程序库的设计者,预测哪些操作最后会用于性能敏感的客户代码是几乎不可能的。在这种特殊情况下,经验、猜测和对客户代码进行大范围的测试这些手段几乎都要用到。比如:ACE就将自己的wrapper facade层的C++类的成员函数内联,我相信这是经过考验的决定。



构造和析构

如果有继承的情况下,一个派生类构造函数总是先调用父类的构造函数,并且编译器要生成代码以正确的设置虚函数表以及虚函数指针(因为父类通常都需要虚析构函数,所以虚函数表通常是避免不了的),以及父类和子类成员变量的初始化。如果这个继承体系较深的话,付出的代价更多。析构函数因为是构造函数的逆过程,同样也要付出较多的代价。因此在一个性能要求很高的系统中,我们设计C++类需要考虑到这个因素,避免产生多余的父类。(这点很难把握,因为一个符合is a的设计,父类会很自然的被设计出来)

如果在组合情况下,一个类的构造函数必须正确初始化其成员变量,如果成员变量有构造函数,那么也有可能会被调用,析构函数同样如此。

虚函数

虚函数好处是利用动态类型提供了更好的抽象,客户代码只需要和基类接口打交道,代码更优雅和便于维护。但是虚函数可能会在三个方面影响性能:

1)虚函数表的布局(前面已有论述)的初始化会对构造和析构函数造成性能开销

2)虚函数都是通过运行时查表,然后调用合适的函数,因此比直接的函数调用慢

3)编译器通常对虚函数的内联处理较困难复杂,有些编译器不支持内联虚函数

前面两个不会造成性能的负担,因为如果不使用虚函数,作为一个常用的替代方案,可以给基类定一个一个类型变量,然后每一个子类型在构造函数中设定该变量的值。这些开销和初始化虚函数表指针变量是相等的。然后,还要使用switch/case语句判断类型,并且进行强制类型转换(从基类指针到子类指针),这些开销等价于虚函数表的查找操作。

看来唯一的问题就是如果虚函数比较简单而且被频繁调用,那么不能内联将导致性能的损失。

虚函数带来的性能问题有时候是可以消除的,想想虚函数和继承的密切关系,如果没有继承的话,也就不会出现虚函数。有一种方法可以让我们减少对继承的依赖,模板。

举个例子,如果有一个MyString类,要支持线程安全,我们可能会有mutex和critical section两种线程同步方案,假设存在两个类,它们都实现了lock和unlock函数:

class CriticalSection

{

public:

void lock();

void unlock();

...
};

class Mutex

{

public:

void lock();

void unlock();

...
};

在这里,我们并不打算让这两个类派生自LockBase类,使得lock和unlock函数成为虚函数,它们就是普通的成员函数。我们将MyString设计成模板类:

template<typename lock>

class MyString

{

private:

lock _lock;

};

使用模板技术,我们将运行时多态替换成编译时多态,我们有效的消除了虚函数,因此lock和unlock函数可以被内联的机率大大增加。

分享到:
评论

相关推荐

    十三MySQL性能优化详解.pdf

    十三MySQL性能优化详解.pdf

    oracle 11g 性能优化扫描版

    oracle 11g数据库性能优化扫描版。目录: 第一章 优化表性能 第二章 选择和优化索引 第三章 优化实例内存 第四章 监控系统性能 第五章 最小化系统资源争夺 第六章 分析操作系统性能 第七章 检修数据库 第八章 创建...

    Asp.NET性能优化.rar

    根据经验的总结,让我们来看看十个能帮助你提升你的应用程序性能的经验,我将按将它们提升效率的多少从大到小小依次说明,一、返回多个数据集,二、对数据进行分页,三、连接池 ,四、 ASP.NET缓存API ,五、 预请求缓存,...

    王哲:Cocos2D游戏性能优化

    Cocos2D这款用于开发2D游戏的开发框架以及由其衍生的Cocos2D-X...目前App Store中国区付费总榜前三十名约有50%是基于Cocos2D开发的。作为Cocos2D-X核心开发者,王哲将分享优化Cocos2D-X、Cocos2D-HTML5游戏性能的案例。

    架构师核心业务+性能优化+架构师运维+架构设计与优化 JAVA真正架构实战教程!

    第十三章 (内容和官网不一样)架构师源码深度剖析 第十二节 保障篇 架构师运维 第十四章第十三节 保障篇 架构师运维 (1)\课程;目录中文件数:2个 (2)\视频 (3)\资料;目录中文件数:6个 ├─content_1600781190674 ├...

    Java程序性能优化之二十三个建议

    NULL 博文链接:https://j2ee2009.iteye.com/blog/690044

    关于Oracle多表连接,提高效率,性能优化操作

    执行路径:ORACLE的这个功能大大地提高了SQL的执行性能并节省了内存的使用:我们发现,单表数据的统计比多表统计的速度完全是两个概念.单表统计可能只要0.02秒,但是2张表联合统计就可能要几十表了. 这是因为ORACLE只对...

    [[高性能MySQL(第3版)].Baron.Scbwartz等.扫描版[电子书.pdf

    第六章查询性能优化;第七章mysql高级特性;第八章优化服务器设置;第九章操作系统和硬件优化;第十章复制;第十一章可扩展的mysql;第十二章高可用性;第十三章云端的mysql;第十四章应用层优化;第十五章备份与...

    mysql必读书籍-高性能mysql第三版.rar

    ◎ 学习MySQL新特性,包括...◎ 实现复制的改进、高可用和集群◎ 获得在云端运行MySQL的高性能 ◎ 优化高级查询特性,如全文索引 ◎ 从现代的多核CPU和固态硬盘中获益 ◎ 探索备份和恢复的策略,包括*的在线备份工具

    Oracle Database 11g性能优化 OCM课第13章

    Oracle Database 11g r2性能调优官方中文版OCM培训教材。

    孙子兵法之sql优化三十六计

    孙子兵法之sql优化三十六计,介绍如何优化sql语句,提升性能,很不错。是中软内部的资料哦。

    性能调优 海量并发 系统架构

    系统性能优化 数据库 Nginx+Squid负载均衡 配置好的集群 总共三十个文档"&gt;Apache+Tomcat+Session+Memcache 高性能群集搭建 J2EE性能调优 Jboss的优化配置 Memcached分布式缓存 Nginx+Tomcat 动静分离 Nginx+tomcat...

Global site tag (gtag.js) - Google Analytics