c - GCC 和 Clang 之间的执行性能差距
问题描述
我有以下简单的代码,当我在 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 之间存在巨大的性能差距?
解决方案
如果您将代码插入https://godbolt.org/,您会看到 Clang 将优化整个 for 循环,这解释了为什么它在 0 秒内执行。它可能会这样做,因为 get 的唯一副作用是 malloc,并且结果会立即释放。
编辑:看起来 GCC 对你的代码确实做得不太好......我再次检查了生成的汇编程序,不仅仅是它无法删除空的 for 循环(for strchr()),而且它也失败了删除循环体中的函数调用(对于 strchr_x())。
所以最后这一切都归结为一些非常奇怪的优化行为,而你最慢的例子实际上是唯一一个可以做任何事情的例子。我不知道为什么GCC 在您的示例中如此失败,但我绝对同意您应该将其作为一个错误提交(甚至可能是两个单独的错误,因为它在使用 strchr() 时已经很难失败,在使用 strchr_x 时更难(),即使两者应该相同)
推荐阅读
- laravel - How to fix ‘HTTP ERROR 500' after deployment Laravel project?
- java - Tune Apache Commons HttpClient logs to Dropwizard
- scala - Cannot resolve overloaded method 'groupByKey'
- c++ - 如何沿行组合两个向量的向量?
- java - 在 Java 中解析从 Django 后端获得的日期时间字符串
- python - 如何在训练过程中纠正不稳定的损失和准确率?(二分类)
- clojure - 通过 List 或 Seq 上的数字索引进行 Clojure 关联解构:意外结果
- android - 像 YouTube 一样的过渡和动画
- java - 滑动变换来选择壁纸的位置?
- database - Spring不会连接数据库并创建表