我昨天遇到了cgroups内存控制器的一个有趣的情况。我一直认为cgroups报告的内存是进程的总内存消耗,但似乎并非如此。
我编写了以下用于测试的Java编程:
import java.util.Scanner;
class TestApp {
public static void main(String args[]) {
int[] arr;
Scanner in = new Scanner(System.in);
System.out.println("Press enter to allocate memory");
in.nextLine();
arr = new int[1024*1024];
System.out.println("Allocated memory");
while(true);
}
}
使用cgexec
运行上述内容时,内存使用情况与echo
将JVM的PID cgroup.procs
放入cgroup的cgexec
文件时大不相同。似乎cgroups报告了之后的内存使用情况>>它被放置在cgroup中。
cgroup如何解释内存?似乎在使用cgroup.procs
时,会考虑JVM的消耗。另一方面,当在cgroup之外启动JVM并稍后通过将PID写入memory.usage_in_bytes
文件将其移入其中时,1024 * 1024 * 4
中报告的内存消耗保持为零,直到我按Enter键消费量达到预期的cgroups
。
此外,top
报告的内存消耗与cgclassify
报告的内存消耗并不完全相同。
编辑:创建以下C程序并将其用于测试。我看到了同样的结果。如果使用cgexec
,则在输入之前内存利用率保持为0。另一方面,当使用#include <stdio.h>
#include <stdlib.h>
int main() {
printf("Press ENTER to consume memory\n");
getchar();
char *ptr = malloc(1024*1024);
if (ptr == NULL) {
printf("Out of memory");
exit(1);
}
memset(ptr, 0, 1024*1024);
printf("Press ENTER to quit\n");
getchar();
return(0);
}
时,内存利用率>在点击进入之前0。
config.omniauth :facebook, ENV['FACEBOOK_KEY'], ENV['FACEBOOK_SECRET'], scope: 'email', info_fields: 'email, name'
答案 0 :(得分:1)
当你分配一个页面并且它被一个进程分页时,分配的内存被标记一个标识符,告诉内核这个内存属于哪个特定的内存控制器cgroup(显然内存也属于任何一个内存) cgroup中)。
将进程迁移到新cgroup时,已分配的内存不会更改其标记。 “重新标记”所有东西是非常昂贵的,甚至没有意义(假设一个页面由两个进程共享,而您只将一个页面迁移到另一个cgroup。“新”标记需要什么?它现在被不同cgroup中的两个进程使用......)
因此,如果您正坐在/ sys / fs / cgroup / memory cgroup中(即您的任务组ID在/ sys / fs / cgroup / memory / tasks中提及,而不是在任何子级的任务文件中) cgroup),你分配的任何东西都是那个 cgroup和那个cgroup的。
当您迁移到其他cgroup(或子cgroup)时,只有 new 内存分配被标记为属于该新cgroup。
cgexec将在 cgroup中启动JVM ,因此在初始化时分配的任何内容都将属于为您执行的内容创建的cgroup。
如果在根cgroup中为内存控制器启动JVM,则初始化JVM时分配和触摸的任何内容都属于根cgroup。
将JVM迁移到自己的私有cgroup(使用任一机制)和然后,您可以分配并触摸某些页面,显然这些将属于新的cgroup。