Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/361.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用cgexec vs cgroup.procs进行使用cgroup的内存记帐_Java_Linux_Linux Kernel_Cgroups - Fatal编程技术网

Java 使用cgexec vs cgroup.procs进行使用cgroup的内存记帐

Java 使用cgexec vs cgroup.procs进行使用cgroup的内存记帐,java,linux,linux-kernel,cgroups,Java,Linux,Linux Kernel,Cgroups,昨天我遇到了一个有趣的情况,使用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.prin

昨天我遇到了一个有趣的情况,使用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的
cgroup.procs
文件时大不相同。似乎在进程被放入cgroup之后,cgroup会报告进程的内存使用情况

cgroup如何解释内存?似乎在使用
cgexec
时,JVM的消耗量会被考虑在内。另一方面,当在cgroup外部启动JVM,然后通过将PID写入
cgroup.procs
文件将其移动到其中时,
memory.usage(以字节为单位)中报告的内存消耗量保持为零,直到我按enter键,消耗量按预期增加到
1024*1024*4

此外,例如,
cgroups
报告的内存消耗与
top
报告的内存消耗并不完全相同

编辑:创建以下C程序并将其用于测试。我也看到了同样的结果。如果使用
cgclassify
,则内存利用率保持为0,直到按enter键。另一方面,当使用
cgexec
时,在按下enter键之前,内存利用率大于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);
}
#包括
#包括
int main(){
printf(“按ENTER键消耗内存\n”);
getchar();
char*ptr=malloc(1024*1024);
如果(ptr==NULL){
printf(“内存不足”);
出口(1);
}
memset(ptr,0,1024*1024);
printf(“按ENTER键退出\n”);
getchar();
返回(0);
}

当您分配一个页面并由一个进程进行分页时,分配的内存会被标记一个标识符,告诉内核该内存属于哪个特定的内存控制器cgroup(显然,该内存也将属于cgroup的任何父级)

将进程迁移到新cgroup时,已分配的内存不会更改其标记。“重新标记”所有内容将非常昂贵,甚至没有意义(假设一个页面由两个进程共享,而您只将其中一个迁移到另一个cgroup。“新”标记需要是什么?它现在由不同cgroup中的两个进程使用…)

因此,如果您位于/sys/fs/cgroup/memory cgroup中(即您的任务组ID在/sys/fs/cgroup/memory/tasks中提到,而不是在该cgroup的任何子级的任务文件中提到),那么您分配的任何内容都只针对该cgroup和该cgroup进行计算

当迁移到其他cgroup(或子cgroup)时,只有新的内存分配被标记为属于该新cgroup

cgexec将在cgroup中启动JVM,因此在初始化时分配的任何内容都将属于为您执行的内容而创建的cgroup

如果在内存控制器的根cgroup中启动一个JVM,那么初始化JVM时分配和触摸的任何东西都将属于根cgroup


一旦您将JVM迁移到它自己的私有cgroup(使用任何一种机制),然后分配和触摸一些页面,显然这些页面将属于新的cgroup。

尝试用C或C++@BasileStrynkevich编写相同的代码谢谢您的建议。我终于能够四处走动并编写一个示例C程序。我看到了同样的结果。。。有什么想法吗?换句话说,如果您希望根据特定于应用程序的内存控制器cgroup计算所有内存,那么您应该创建cgroup并在开始应用程序之前将“您自己”移动到该cgroup。--要手动执行此操作,只需在根cgroup下创建一个目录,然后在shell中创建,例如echo$$>/sys/fs/cgroup/memory/my_private\u cgroup/tasks。如果您从该shell(现在位于my_private_cgroup cgroup中)启动JVM,它从一开始就位于正确的cgroup中。谢谢Alexis。这上面有文件吗?我在memory.txt中找不到任何内容