【发布时间】:2015-02-26 04:50:51
【问题描述】:
在分析我的应用程序时,我意识到很多时间都花在了字符串比较上。所以我写了一个简单的基准测试,我很惊讶 '==' 比 string::compare 和 strcmp 慢得多!这是代码,谁能解释这是为什么?或者我的代码有什么问题?因为根据标准 '==' 只是一个运算符重载,只是返回 !lhs.compare(rhs)。
#include <iostream>
#include <vector>
#include <string>
#include <stdint.h>
#include "Timer.h"
#include <random>
#include <time.h>
#include <string.h>
using namespace std;
uint64_t itr = 10000000000;//10 Billion
int len = 100;
int main() {
srand(time(0));
string s1(len,random()%128);
string s2(len,random()%128);
uint64_t a = 0;
Timer t;
t.begin();
for(uint64_t i =0;i<itr;i++){
if(s1 == s2)
a = i;
}
t.end();
cout<<"== took:"<<t.elapsedMillis()<<endl;
t.begin();
for(uint64_t i =0;i<itr;i++){
if(s1.compare(s2)==0)
a = i;
}
t.end();
cout<<".compare took:"<<t.elapsedMillis()<<endl;
t.begin();
for(uint64_t i =0;i<itr;i++){
if(strcmp(s1.c_str(),s2.c_str()))
a = i;
}
t.end();
cout<<"strcmp took:"<<t.elapsedMillis()<<endl;
return a;
}
结果如下:
== took:5986.74
.compare took:0.000349
strcmp took:0.000778
还有我的编译标志:
CXXFLAGS = -O3 -Wall -fmessage-length=0 -std=c++1y
我在 x86_64 linux 机器上使用 gcc 4.9。
显然使用 -o3 做了一些优化,我猜这会完全推出最后两个循环;但是,使用 -o2 的结果仍然很奇怪:
10 亿次迭代:
== took:19591
.compare took:8318.01
strcmp took:6480.35
附: Timer 只是一个用于测量花费时间的包装类;我对此非常肯定:D
Timer 类的代码:
#include <chrono>
#ifndef SRC_TIMER_H_
#define SRC_TIMER_H_
class Timer {
std::chrono::steady_clock::time_point start;
std::chrono::steady_clock::time_point stop;
public:
Timer(){
start = std::chrono::steady_clock::now();
stop = std::chrono::steady_clock::now();
}
virtual ~Timer() {}
inline void begin() {
start = std::chrono::steady_clock::now();
}
inline void end() {
stop = std::chrono::steady_clock::now();
}
inline double elapsedMillis() {
auto diff = stop - start;
return std::chrono::duration<double, std::milli> (diff).count();
}
inline double elapsedMicro() {
auto diff = stop - start;
return std::chrono::duration<double, std::micro> (diff).count();
}
inline double elapsedNano() {
auto diff = stop - start;
return std::chrono::duration<double, std::nano> (diff).count();
}
inline double elapsedSec() {
auto diff = stop - start;
return std::chrono::duration<double> (diff).count();
}
};
#endif /* SRC_TIMER_H_ */
【问题讨论】:
-
如果您在一毫秒内看到任何事物的 100 亿次迭代,那么您真的应该质疑基准本身...
-
您的
strcmp代码错误。你应该在那里做== 0。 -
如果您将
==基准换成.compare基准,您会得到相同的结果吗? -
我的电脑花了 6 多分钟才通过
==代码,6 分钟后我终止了程序。把100亿改成100万得到了这些结果:== took:37.5232.compare took:19.3218strcmp took:12.3108 -
我看了汇编语言。似乎对于 compare 和 strcmp 的情况,如果第一次迭代是!= 0,那么它完全退出循环。从语义上讲,这是正确的。 == 情况并非如此。我猜编译器真的很聪明,但还不够聪明。另外, == 不打电话。我猜它是内联的。这种内联可能导致优化出现问题。