为什么更新大数组使“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 - 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 version gcc(GCC)4.8.2 20140120(Red Hat 4.8.2-16)

服务器AWS EC2 r3.8xlarge

操作系统Amazon Linux AMI发布2014.09

这是与Why does `change_protection` hog CPU while loading a large amount of data into RAM?相关的问题

最佳答案 那么会发生什么:

>你的malloc代码.这意味着内核将页面映射到程序的空间;为此,页面甚至不必可用,它更像是“一旦你实际访问该内存就通知我”的情况.
>您的第一个循环按顺序访问页面.因此,内核经常需要将实际内存分配给以前未使用的页面.可能,AWS虚拟机管理程序正在快速从其池中提供该内存
>你再次访问这些页面 – 但是由于运气不好,160GB区域开头的页面现在可能“远”了,让它们靠近运行代码的CPU可能会很慢.请记住,您在类似于NUMA计算机的虚拟机上运行.

编辑它对SIGTERM等没有反应的事实并不令人惊讶 – 没有明确的上下文切换发生,并且在for循环中没有完成信号检查,所以你的程序无法对信号作出反应.

点赞