首页 > 解决方案 > 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 秒。

所以,我的问题是:

  1. 为什么我的 'strchr_x' 和 GCC 中标准库的 'strchr' 之间存在巨大的性能差异?
  2. 为什么 GCC 和 Clang 之间存在巨大的性能差距?

标签: cgccclang

解决方案


如果您将代码插入https://godbolt.org/,您会看到 Clang 将优化整个 for 循环,这解释了为什么它在 0 秒内执行。它可能会这样做,因为 get 的唯一副作用是 malloc,并且结果会立即释放。

编辑:看起来 GCC 对你的代码确实做得不太好......我再次检查了生成的汇编程序,不仅仅是它无法删除空的 for 循环(for strchr()),而且它失败了删除循环体中的函数调用(对于 strchr_x())。

所以最后这一切都归结为一些非常奇怪的优化行为,而你最慢的例子实际上是唯一一个可以做任何事情的例子。我不知道为什么GCC 在您的示例中如此失败,但我绝对同意您应该将其作为一个错误提交(甚至可能是两个单独的错误,因为它在使用 strchr() 时已经很难失败,在使用 strchr_x 时更难(),即使两者应该相同)


推荐阅读