C++ 性能剖析 (一),性能剖析_PHP教程
C++ 性能剖析 (一),性能剖析
C++ 性能剖析 (一)
性能问题也不是仅仅用“技术”可以解决的,它往往是架构,测试,假设等综合难题。不过,对于一个工程师来说,必须从小做起,把一些“明显”的小问题解决。否则的话积小成多,千里堤坝,溃于蚁穴。
C++ 的性能为什么总是排在C之后 (见http://benchmarksgame.alioth.debian.org/u32/performance.php?test=binarytrees 等网站的最新测试结果)?我认为这是3个方面的原因:
1)用于测试的C++ 编译器没有使用最新的优化技术
2)C++ 附加的价值没有考虑到测试之中
3)C++ 应用层面的“微妙性”(可参考我的关于C++的其他博客)使得一般程序员往往望而却步,选择“教科书用例”,使得一些副作用没有在应用层面被剔出。
记得10多年前,我在微软做开发时,曾向C++最早编译器的作者李伯曼(Stan Lippman)(时任微软VC++架构师)咨询过一系列我们小组的C++性能难题,在他的帮助下,我们在关键地方用了诸如inline,RVO等技术,完全解决了性能问题,还找出了VC++ 的几个不小的错误。我认识到,C++的性能问题多数在于我们对C++认识的浅薄,多数都是不难解决的。
下面用一例子,来做一下对比,看看一些微妙的细节是如何影响程序性能的。
struct intPair
{
int ip1;
int ip2;
intPair(int i1, int i2) : ip1(i1), ip2(i2) {}
intPair(int i1) : ip1(i1), ip2(i1) {}
};
// Calc sum (usinh value semantic)
Int Sum1(intPair p)
{
return p.ip1 + p.ip2;
}
// Calc sum (usinh ref semantic)
int Sum2(intPair &p)
{
return p.ip1 + p.ip2;
}
// Calc sum (usinh const ref semantic)
Int Sum3(const intPair& p)
{
return p.ip1 + p.ip2;
}
上面这个简单的struct,有三个Sum函数,作的事情完全一样,但是性能是否一样呢?我们用下面的程序来测试:
double Sum(int t, int loop)
{
using namespace std;
if (t == 1)
{
clock_t begin = clock();
int x =0;
for(int i = 0; i
{
x += Sum1(intPair(1,2));
}
clock_t end = clock();
return double(end - begin) / CLOCKS_PER_SEC;
}
else if (t == 2)
{
clock_t begin = clock();
int x =0;
intPair p(1,2);
for(int i = 0; i
{
x += Sum1(p);
}
clock_t end = clock();
return double(end - begin) / CLOCKS_PER_SEC;
}
else if (t == 3)
{
clock_t begin = clock();
int x =0;
intPair p(1,2);
for(int i = 0; i
{
x += Sum2(p);
}
clock_t end = clock();
return double(end - begin) / CLOCKS_PER_SEC;
}
else if (t == 4)
{
clock_t begin = clock();
int x =0;
intPair p(1,2);
for(int i = 0; i
{
x += Sum3(p);
}
clock_t end = clock();
return double(end - begin) / CLOCKS_PER_SEC;
}
else if (t == 5)
{
clock_t begin = clock();
int x =0;
for(int i = 0; i
{
x += Sum3(10);
}
clock_t end = clock();
return double(end - begin) / CLOCKS_PER_SEC;
}
return 0;
}
我们用了5个案列,对Sum1和Sum3 风别用了两种调用方式,对Sum2用了一种调用方式。我们测试了10万次调用:
double sec = Sum(1, 100000);
printf("Sum1 (use ctor) time: %f \n", sec);
sec = Sum(2, 100000);
printf("Sum1 (use no c'tor) time: %f \n", sec);
sec = Sum(3, 100000);
printf("Sum2 time: %f \n", sec);
sec = Sum(4, 100000);
printf("Sum3 without conversion time: %f \n", sec);
sec = Sum(5, 100000);
printf("Sum3 with conversion time: %f \n", sec);
我们在VisualStidio 2010 中测试,结果是:
用例1 18ms
用例2 9ms
用例3 6ms
用例4 7ms
用例5 12ms
也就是说:用例1和5最慢,其他基本没有差别。
细心的读者不难看出,
1)用例5的性能问题,是因为Sum3用了C++的implicit conversion ,将整数自动转化成intPair 的临时变量。这是一个应用层面的问题,如果我们不得不将整数作这个转换,也就不得不付出这个性能上的代价。
2)用例1的问题和5类似,都是因为不得不每次创建临时变量。当然,可以强迫constructor inline 来使得临时变量的生成成本降低。
3)用例2用了在函数调用前了编译自生的copy constructor,不过因为 intPair object 很小,影响可以忽略不计了。
4)用例3性能是稳定的,但是它用了“间接”方式(详情请看我关于reference的博克),所以产生的指令比用例2多两条。但对性能的影响不大,估计和Intel的L1,L2 缓存有关。
*注意到OOP函数如果仅仅对 this 的成员存取数据,一般可以充分利用缓存,除非 object 过大。
5)用例4 和用例3生成代码完全一样,应该没有差别。const 只是编译时有用,生成的代码与const 与否无关。
性能问题的话题太多,本文只是蜻蜓点水,但是已经触及了C++的两个最大的性能隐患:
a) 临时变量
b) Implicit conversion (沉默转换)
2014-6-20 西雅图
没时间帮你写程序需说个思路就闪人了 你先把3种排序的书上的例子抄下来 写成3个函数, 每个函数里面开头和结尾取一次系统时间 最后相减得出开销时间 在打印出来
我把网上的程序修改了一下,并整合了,你看看
#include
#include
#include
#define M 50
#define MAX 100000;
typedef struct
{
int weight;//结点权值
int parent,lchild,rchild;
}HTNODE,*HUFFMANTREE;
typedef char** HUFFMANCODE;//动态分配数组存储哈夫曼编码表
typedef struct
{
int key; /*关键字*/
}RecordNode; /*排序节点的类型*/
typedef struct
{
RecordNode *record;
int n; /*排序对象的大小*/
}SortObject; //待排序序列
HUFFMANTREE huffmantree(int n,int weight[])//构建哈夫曼树
{
int m1,m2,k;
int i,j,x1,x2;
HUFFMANTREE ht;
ht=(HUFFMANTREE)malloc((2*n)*sizeof(HTNODE));
for(i=1;i{
ht[i].parent=ht[i].lchild=ht[i].rchild=0;
if(iht[i].weight=weight[i];
else
ht[i].weight=0;
}
for(i=1;i
m1=m2=MAX;
x1=x2=0;
for(j=1;j{
if((ht[j].weight
m2=m1;
x2=x1;
m1=ht[j].weight;
x1=j;
}
else if((ht[j].weight
m2=ht[j].weight;
x2=j;
}
}
k=n+i;
ht[x1].parent=ht[x2].parent=k;
ht[k].weight=m1+m2;
ht[k].lchild=x1;
ht[k].rchild=x2;
}
return ht;
}
void huffmancoding(int n,HUFFMANCODE hc,HUFFMANTREE ht,char str[])
{
int i,start,child,father;
char *cd;
hc=(HUFFMANCODE)malloc((n+1)*sizeof(char*));//分配n个字符编码的头指针
cd=(char*)malloc(n*sizeof(char));//分配求编码的工作空间
cd[n-1]='\0';//编码结束符
f......余下全文>>

핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

뜨거운 주제











종종 키워드와 추적 매개 변수로 혼란스러워하는 긴 URL은 방문자를 방해 할 수 있습니다. URL 단축 스크립트는 솔루션을 제공하여 소셜 미디어 및 기타 플랫폼에 이상적인 간결한 링크를 만듭니다. 이 스크립트는 개별 웹 사이트 a에 유용합니다

Laravel은 직관적 인 플래시 방법을 사용하여 임시 세션 데이터 처리를 단순화합니다. 응용 프로그램에 간단한 메시지, 경고 또는 알림을 표시하는 데 적합합니다. 데이터는 기본적으로 후속 요청에만 지속됩니다. $ 요청-

이것은 Laravel 백엔드가있는 React Application을 구축하는 데있어 시리즈의 두 번째이자 마지막 부분입니다. 이 시리즈의 첫 번째 부분에서는 기본 제품 목록 응용 프로그램을 위해 Laravel을 사용하여 편안한 API를 만들었습니다. 이 튜토리얼에서는 Dev가 될 것입니다

Laravel은 간결한 HTTP 응답 시뮬레이션 구문을 제공하여 HTTP 상호 작용 테스트를 단순화합니다. 이 접근법은 테스트 시뮬레이션을보다 직관적으로 만들면서 코드 중복성을 크게 줄입니다. 기본 구현은 다양한 응답 유형 단축키를 제공합니다. Illuminate \ support \ Facades \ http를 사용하십시오. http :: 가짜 ([ 'google.com'=> 'Hello World', 'github.com'=> [ 'foo'=> 'bar'], 'forge.laravel.com'=>

PHP 클라이언트 URL (CURL) 확장자는 개발자를위한 강력한 도구이며 원격 서버 및 REST API와의 원활한 상호 작용을 가능하게합니다. PHP CURL은 존경받는 다중 프로모토콜 파일 전송 라이브러리 인 Libcurl을 활용하여 효율적인 execu를 용이하게합니다.

고객의 가장 긴급한 문제에 실시간 인스턴트 솔루션을 제공하고 싶습니까? 라이브 채팅을 통해 고객과 실시간 대화를 나누고 문제를 즉시 해결할 수 있습니다. 그것은 당신이 당신의 관습에 더 빠른 서비스를 제공 할 수 있도록합니다.

2025 PHP Landscape Survey는 현재 PHP 개발 동향을 조사합니다. 개발자와 비즈니스에 대한 통찰력을 제공하는 프레임 워크 사용, 배포 방법 및 과제를 탐색합니다. 이 조사는 현대 PHP Versio의 성장을 예상합니다

이 기사에서는 Laravel 웹 프레임 워크에서 알림 시스템을 탐색 할 것입니다. Laravel의 알림 시스템을 사용하면 다른 채널을 통해 사용자에게 알림을 보낼 수 있습니다. 오늘은 알림을 보낼 수있는 방법에 대해 논의합니다
