有人可以解释以下内存分配 C 程序的性能行为吗?

标签 c linux performance unix compiler-construction

在我的机器上时间 A 和时间 B 交换取决于 A 是否是 是否定义(这会改变调用两个 calloc 的顺序)。

我最初将此归因于寻呼系统。奇怪的是,当 mmap 被用来代替 calloc,情况更加奇怪——正如预期的那样,两个循环花费相同的时间。作为 可以通过 strace 看到,calloc 最终导致两个 mmaps,因此没有返回已分配内存的魔法。

我正在 Intel i7 上运行 Debian 测试。

#include <stdlib.h>
#include <stdio.h>
#include <sys/mman.h>

#include <time.h>

#define SIZE 500002816

#ifndef USE_MMAP
#define ALLOC calloc
#else
#define ALLOC(a, b) (mmap(NULL, a * b, PROT_READ | PROT_WRITE,  \
                          MAP_PRIVATE | MAP_ANONYMOUS, -1, 0))
#endif

int main() {
  clock_t start, finish;
#ifdef A
  int *arr1 = ALLOC(sizeof(int), SIZE);
  int *arr2 = ALLOC(sizeof(int), SIZE);
#else
  int *arr2 = ALLOC(sizeof(int), SIZE);
  int *arr1 = ALLOC(sizeof(int), SIZE);
#endif
  int i;

  start = clock();
  {
    for (i = 0; i < SIZE; i++)
      arr1[i] = (i + 13) * 5;
  }
  finish = clock();

  printf("Time A: %.2f\n", ((double)(finish - start))/CLOCKS_PER_SEC);

  start = clock();
  {
    for (i = 0; i < SIZE; i++)
      arr2[i] = (i + 13) * 5;
  }
  finish = clock();

  printf("Time B: %.2f\n", ((double)(finish - start))/CLOCKS_PER_SEC);

  return 0;
}

我得到的输出:

 ~/directory $ cc -Wall -O3 bench-loop.c -o bench-loop
 ~/directory $ ./bench-loop 
Time A: 0.94
Time B: 0.34
 ~/directory $ cc -DA -Wall -O3 bench-loop.c -o bench-loop
 ~/directory $ ./bench-loop                               
Time A: 0.34
Time B: 0.90
 ~/directory $ cc -DUSE_MMAP -DA -Wall -O3 bench-loop.c -o bench-loop
 ~/directory $ ./bench-loop                                          
Time A: 0.89
Time B: 0.90
 ~/directory $ cc -DUSE_MMAP -Wall -O3 bench-loop.c -o bench-loop 
 ~/directory $ ./bench-loop                                      
Time A: 0.91
Time B: 0.92

最佳答案

您还应该使用 malloc 而不是 calloc 进行测试。 calloc 做的一件事是用零填充分配的内存。

我相信在你的情况下,当你最后一次calloc arr1 然后分配给它时,它已经被错误地放入缓存内存中,因为它是最后一个分配和零填充的。当您首先调用 arr1,然后调用 arr2 时,arr2 的零填充会将 arr1 推出缓存。

关于有人可以解释以下内存分配 C 程序的性能行为吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10096294/

相关文章:

c++ - Windows 上 glibc 的 backtrace() 和 backtrace_symbols() 的对应物?

c - 如何在 C 语言中的两个独立应用程序之间使用共享内存

正则表达式以递归方式重命名所有文件,删除字符 "?"命令行后的所有内容

vb.net - 同一算法的两种实现之间的性能差异

sql-server - 使用 SUM() 而不使用 ISNULL() 是否安全

c# - 为什么我的 NHibernate 查询这么慢?

c - Makefile:两个不同的可执行文件采用两个重叠的代码子集

java - JNI 中的 UnsatisfiedLinkError

c - 为什么运算符 >> 不适用于我的字符设备?

linux - 将文件内容读取到 grub.cfg 文件中的变量