为什么更新大数组使得“change_protection”内核调用占主导地位的CPU?

这里是代码gcc test.c -std=c99

 #include <stdio.h> #include <stdlib.h> void main() { size_t size = (long) 40 * 1024 * 1024 * 1024; int* buffer = malloc(size * sizeof(int)); for (size_t i = 0; i < size; i++) { buffer[i] = 1; } printf("hello\n"); for (size_t i = 0; i < size; i++) { buffer[i] = 2; } printf("hello\n"); } 

160G的RAM一次性分配,并遍历两次

第一个循环运行愉快

然而程序有点卡在第二循环内

与性能perf top显示此

 Samples: 7M of event 'cpu-clock', Event count (approx.): 14127849698 74.95% [kernel] [k] change_protection 23.52% [kernel] [k] vm_normal_page 0.40% [kernel] [k] _raw_spin_lock 0.34% [kernel] [k] _raw_spin_unlock 

top显示这一点

 top - 10:52:36 up 55 min, 4 users, load average: 1.16, 1.18, 1.04 Tasks: 240 total, 2 running, 238 sleeping, 0 stopped, 0 zombie Cpu(s): 0.0%us, 3.1%sy, 0.0%ni, 96.9%id, 0.0%wa, 0.0%hi, 0.0%s Mem: 251913536k total, 170229472k used, 81684064k free, 27820k b Swap: 0k total, 0k used, 0k free, 352816k cac PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 12825 dapeng 20 0 160g 160g 376 R 100.0 66.6 30:38.55 a.out 

而最好的部分是现在这个程序不再回应kill命令了

gcc版本gcc (GCC) 4.8.2 20140120 (Red Hat 4.8.2-16)

服务器AWS EC2 r3.8xlarge

操作系统Amazon Linux AMI release 2014.09

这是一个相关的问题, 为什么在将大量数据加载到RAM中时,change_protection会占用CPU?

那么会发生什么呢?

  1. 你的malloc代码。 这意味着内核将页面映射到程序空间中; 为此,网页甚至不必可用,它更多的是“通知我,一旦你实际访问内存”的情况。
  2. 你的第一个循环顺序访问页面。 因此,内核经常不得不将真实的内存分配给以前不用的页面。 AWS管理程序可能很快从其池中提供该内存
  3. 你再次访问这些页面 – 但是如果运气不好,160GB区域开始的页面现在可能已经“远离”了,并且让它们靠近你的代码运行的CPU可能会很慢。 请记住,您正在虚拟机上运行类似于NUMA机器的虚拟机。

编辑它不会对SIGTERM做出反应的事实并不奇怪 – 没有明确的上下文切换发生,也没有在for循环中进行信号检查,所以没有可以让程序对信号做出反应的地方。