readme
各路大神每天都在宣贯各种各样的方法论,哪个算法最牛,哪个框架最牛,哪个等等等。今天我通过这篇博客详细对比一下最基础的编译优化选项,连地基都还没搭好,就先别琢磨阁楼的装饰了,LOL~。
编译优化选项简介
这篇博客的编译优化选项指的就是g++命令的-O参数,根据linux man-pages介绍,g++的-O参数有7中,分别为:
- -O0。默认参数,对程序性能没有优化效果。
- -O1。与-O0相比,编译耗时更久,可执行文件更小,性能更好,较大的函数会占更多内存。
- -O2。推荐参数。编译耗时更久,代码性能更好。
- -O3。-O2的基础上进一步优化。
- -Os。优化可执行文件大小。
- -Ofast。-O3的基础上进一步优化。
- -Og。优化debug体验。
上面的介绍很简单,仅仅贴出了有信息量的部分。比较常用的就是-O0和-O2了,其他选项意义不大。这篇博客会用一个真实的例子对比-O0和-O2的差距。
测试程序
//common.h
#ifndef _COMMON_H_
#define _COMMON_H_
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <iostream>
#include <utility>
#include <algorithm>
#include <vector>
#include <iterator>
#include <sys/time.h>
using namespace std;
#endif
//Timer.h
#ifndef _TIMER_H
#define _TIMER_H
#include <sys/time.h>
#include "common.h"
class Timer
{
public:
Timer(string strCallInfo = "Timer", bool us_need = false)
{
_desc = strCallInfo;
_us_need = us_need;
gettimeofday(&_begin, NULL);
gettimeofday(&_end, NULL);
};
~Timer()
{
gettimeofday(&_end,NULL);
printf("%s, cost %ldms\n", _desc.c_str(), (_end.tv_sec - _begin.tv_sec) * 1000 + (_end.tv_usec - _begin.tv_usec) / 1000);
if (_us_need)
{
printf("%s, cost %ldus\n", _desc.c_str(), (_end.tv_sec - _begin.tv_sec) * 1000000 + _end.tv_usec - _begin.tv_usec);
}
};
private:
Timer(){};
string _desc;
bool _us_need;
timeval _begin;
timeval _end;
};
#endif
//opt_param.cpp
#include "common.h"
#include "Timer.h"
int main(void){
string testStr(1024 * 1024, 'a');
{
Timer count("g++ optimization test");
vector<pair<string, string>> testVec(1024 * 1024);
for (size_t i = 0; i < 1024 * 1024; ++i)
{
testVec.push_back(make_pair(testStr, testStr));
}
}
return 0;
}
编译和执行结果
g++ -o opt_param opt_param.cpp -std=c++11 -O0
./opt_param
g++ optimization test, cost 172ms
g++ -o opt_param opt_param.cpp -std=c++11 -O2
./opt_param
g++ optimization test, cost 46ms
测试程序解释
测试代码很简单,基本一眼就能看懂,但从执行结果可以发现-O0和-O2的明显差距。不得不说的一点是,针对不同种类的逻辑,-O参数带来的优化幅度也不一样。但终归-O参数的合理选择,对于一个性能敏感的项目是不可忽略的。有人认为-O2会导致debug很不方便,但一个正规的流程中,线上debug本身就是不该有的。