1

昨日、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);
  }

}

上記を で実行すると、メモリ使用量は、JVM の PID をcgroup のファイルに ing するcgexec場合とは大きく異なります。プロセスが cgroup 内に配置された、cgroup がそのプロセスのメモリ使用量を報告しているようです。echocgroup.procs

cgroup はメモリをどのように考慮しますか? cgexecを使用すると、JVMの消費が考慮されるようです。一方、cgroup の外部で JVM を起動し、後で PID をファイルに書き込んで cgroup に移動すると、Enter キーを押して消費量が期待どおりになるまで、cgroup.procs報告されたメモリ消費量はゼロのままです。memory.usage_in_bytes1024 * 1024 * 4

さらに、 によって報告されるメモリ消費量は、たとえばcgroupsによって報告されるメモリ消費量と完全に同じではありません。top

編集:次のCプログラムを作成し、テストに使用しました。私は同じ結果を見ています。を使用している場合cgclassify、Enter キーを押すまでメモリ使用率は 0 のままです。一方、 を使用する場合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);
}
4

1 に答える 1

2

ページを割り当て、それがプロセスによってページインされると、割り当てられたメモリは識別子でタグ付けされ、このメモリが属する特定のメモリ コントローラー cgroup をカーネルに通知します (明らかに、メモリは cgroup の任意の親にも属します)。

プロセスを新しい cgroup に移行しても、既に割り当てられているメモリのタグは変更されません。すべてを「再タグ付け」するには非常にコストがかかり、意味がありません (1 つのページが 2 つのプロセスで共有されていて、そのうちの 1 つだけを別の cgroup に移行するとします。「新しい」タグは何が必要でしょうか?現在、異なる cgroup の 2 つのプロセスで使用されています...)

したがって、/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 に属します。

于 2016-01-15T10:28:51.070 に答える