char s[] = "This string has * many space (0x20) chars. *";
for (size_t i = 0 ; i < sizeof (s); ++i){
if (s[i] == ' ')
s[i] = '*';
}
}
复制代码
for(part 1 ; part 2 ; part 3 ) 语句包含了三部分,第一部分是初始化语句,第二部分是从每次循环开始判断是否执行本次循环内的语句。第三部分是每次执行完成之后运行的。
从这里我们可以看到,part 2 是会一直运行的,如果在这部分当中包含了一个运行开销比较大的操作,那这部分就会造成很多的运行消耗。可以看到在debug模式下的运行输出
缓存条件语句
如果我们把part 2 当中的sizeof操作符号放到part 1 当中,代码如下:
void testFunc_RemoveSizeof(){
char s[] = "This string has * many space (0x20) chars. *";
for (size_t i = 0 ,len = sizeof (s); i < len; ++i){
if (s[i] == ' ')
s[i] = '*';
}
}
复制代码
可以看到在debug模式下的运行结果
testFunc_RemoveSizeof: start
testFunc_RemoveSizeof: stop Total take
407806 ticks and takes 407 mS
但是如果在release模式下,实际上这两种方式运行结果是相同的。
testFunc_Origin: start
testFunc_Origin: stop
Total take 11743 ticks and takes 11 mS
testFunc_RemoveSizeof: start
testFunc_RemoveSizeof: stop
Total take 11708 ticks and takes 11 mS
Process finished with exit code 0
这是因为编译器实际上为我们进行了优化。如果我们把编译器的优化等级调低的话,
set(CMAKE_CXX_FLAGS_RELEASE “-O2”)
那么结果就是
testFunc_Origin: start
testFunc_Origin: stop
Total take 18598 ticks and takes 18 mS
testFunc_RemoveSizeof: start
testFunc_RemoveSizeof: stop
Total take 34442 ticks and takes 34 mS
可以看到,在优化选项不同的时候,效果会不同。
更改循环方式
基本上说,for循环在编译后会编程 if / goto/类似的语句,这种跳转语句可能会降低运行速度,如果我们更换一种循环方式的话
void testFunc_DoWhile(){
char s[] = "This string has * many space (0x20) chars. *";
size_t i = 0, len = sizeof(s); // for循环初始化表达式
do {
if (s[i] == ' ')
s[i] = ' ';
++i; // for循环继续表达式
} while (i < len); // for循环条件
}
复制代码
结果如下:
testFunc_DoWhile: start
testFunc_DoWhile: stop
Total take 405896 ticks and takes 405 mS
移除不变性代码