我一直用以下代码测量初始化字符串的速度,发现奇怪的事情:
#include <stdio.h>
#include <time.h>
#define START_COUNTING clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &start)
#define END_COUNTING clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &end)
#define NUM_OF_LOOPS 8192
long time_difference(struct timespec end, struct timespec beginning) {
long long diff = (long long)end.tv_sec - (long long)beginning.tv_sec;
return(end.tv_nsec - beginning.tv_nsec + ((diff > 0) ? 1000000L : 0));
}
long average(long numbers[NUM_OF_LOOPS]) {
long long sum = 0;
int i;
for(i = 0; i < NUM_OF_LOOPS; i++)
sum += numbers[i];
return sum / NUM_OF_LOOPS;
}
int main(void) {
struct timespec start;
struct timespec end;
long time_diffs[NUM_OF_LOOPS];
int i;
char * str = NULL;
for(i = 0; i < NUM_OF_LOOPS; i++) {
START_COUNTING;
str = "T";
END_COUNTING;
time_diffs[i] = time_difference(end, start);
}
printf("%li ns - assigning 2 chars to a string\n", average(time_diffs));
for(i = 0; i < NUM_OF_LOOPS; i++) {
START_COUNTING;
str = "Testing";
END_COUNTING;
time_diffs[i] = time_difference(end, start);
}
printf("%li ns - assigning 8 chars to a string\n", average(time_diffs));
for(i = 0; i < NUM_OF_LOOPS; i++) {
START_COUNTING;
str = "Testing it here";
END_COUNTING;
time_diffs[i] = time_difference(end, start);
}
printf("%li ns - assigning 16 chars to a string\n", average(time_diffs));
for(i = 0; i < NUM_OF_LOOPS; i++) {
START_COUNTING;
str = "Lorem ipsum dolor sit amet, consectetur adipiscing elit nullam.";
END_COUNTING;
time_diffs[i] = time_difference(end, start);
}
printf("%li ns - assigning 64 chars to a string\n", average(time_diffs));
for(i = 0; i < NUM_OF_LOOPS; i++) {
START_COUNTING;
str = ""; // String omitted because it would waste a lot of space
END_COUNTING;
time_diffs[i] = time_difference(end, start);
}
printf("%li ns - assigning 1024 chars to a string\n", average(time_diffs));
return 0;
}
在分析它时,我总是想出这个结果:
1126 ns - assigning 2 chars to a string
828 ns - assigning 8 chars to a string
832 ns - assigning 16 chars to a string
834 ns - assigning 64 chars to a string
857 ns - assigning 1024 chars to a string
第一个结果,无论它是否分配2个字符,8个字符或多个字符总是明显慢于其余字符。我已经尝试在循环之前放置1个赋值,但它仍然没有太多改变结果。
有谁知道为什么分配给字符串的前几次更慢?我环顾四周,但只找到了因JIT编译器而发生的答案,但C并没有使用它们。
答案 0 :(得分:2)
您的代码实际上并不复制任何字符数据,因为您只是设置指向字符串文字的指针。
因此,整个前提是错误的,并且“已分配”的字符数与所花费的时间之间没有相关性。
这是一个超微基准测试,并且非常难以实现,因为您实际上是在尝试测量单个指针大小分配所花费的时间,这实际上并不是很多代码。
速度差异可能是由缓存/内存延迟引起的。您可以阅读生成的代码,以确定str
是否存储在寄存器中,当然也可以使用优化设置。
注意:您的测量方法,平均值,意味着开销(time_diffs
数组)的缓存占用量 大于测试本身的高度,这可能是导致不规则,第一次time_diffs
没有被缓存。
答案 1 :(得分:0)
这里有两个重要的项目: -
第一个是显而易见的,第二个不是这样。例如,此代码: -
for(i = 0; i < NUM_OF_LOOPS; i++) {
START_COUNTING;
str = "T";
END_COUNTING;
time_diffs[i] = time_difference(end, start);
}
很可能是由优化编译器编译的: -
for(i = 0; i < NUM_OF_LOOPS; i++) {
START_COUNTING;
END_COUNTING;
time_diffs[i] = time_difference(end, start);
}
str = "T";
第一个循环缓慢的原因,可能是缓存。 cpu必须从RAM / HD加载代码,这需要一段时间,特别是当你在那里进行函数调用时。尝试在定时循环之前放置它: -
START_COUNTING;
END_COUNTING;
希望代码进入缓存,为时序循环做好准备。