【发布时间】:2019-11-08 08:09:15
【问题描述】:
我有以下简单代码,当我在 GCC 和 Clang 中编译它们时,它们的执行时间之间存在巨大的性能差异,您可以在下面看到结果和编译器的版本。
char* strchr_x(register const char* s, int c) {
do {
if (*s == c) {
return (char*)s;
}
} while (*s++);
return 0;
}
char* get(char* value, const char separator) {
int separator_index = strchr(value, separator) - value;
char* result = malloc(separator_index);
memcpy(result, value, separator_index);
result[separator_index] = '\0';
return result;
}
int main() {
const char separator = ',';
clock_t t = clock();
for (size_t i = 0; i < 100000000; ++i) {
free(get("127.0.0.1, 127.0.0.2:1111", separator));
}
float elapsed_seconds = (((double)(clock() - t)) / CLOCKS_PER_SEC);
printf("%f seconds.\n", elapsed_seconds);
return 0;
}
gcc version 8.1.0 (Ubuntu 8.1.0-5ubuntu1~16.04)
# gcc main.c -O3 -o gcc-main
# 1.968750 seconds.
clang version 3.8.0-2ubuntu4 (tags/RELEASE_380/final)
# clang main.c -O3 -o clang-main
# 0.000000 seconds.
此外,“strchr_x”实现与原始 GCC 实现完全相同。你可以在https://github.com/gcc-mirror/gcc/blob/master/libiberty/strchr.c看到它
当我在标准库中使用'strchr'方法时; GCC 的运行时间减少到 0.015625 秒。
所以,我的问题是:
- 为什么我的 'strchr_x' 和 GCC 中标准库的 'strchr' 之间存在巨大的性能差异?
- 为什么 GCC 和 Clang 之间存在如此巨大的性能差距?
【问题讨论】:
-
显然 clang 优化了 /* no effect */ for 循环。看看拆解。
-
当时间为零时,意味着编译器完全优化了您尝试测试的代码。它可以这样做,因为代码没有任何可观察到的效果。
-
您有未定义的行为(写到
result的末尾)。不过,这可能不是导致性能差异的原因。 -
gcc 将循环减少到
for(unsigned long x=10000000;x!=0;--x);,然后无法删除这个空循环。请在 gcc 的 bugzilla 中提交错误报告。在 main 上添加__attribute__((flatten))以便更早地进行内联可以让 gcc 优化,但它确实应该能够做到这一点而不会作弊。