1

私は次の単純なプログラムを持っています。これは基本的にmmapファイルを保存し、その中のすべてのバイトを合計します:

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>

volatile uint64_t sink;

int main(int argc, char** argv) {

  if (argc < 3) {
    puts("Usage: mmap_test FILE populate|nopopulate");
    return EXIT_FAILURE;
  }

  const char *filename = argv[1];
  int populate = !strcmp(argv[2], "populate");
  uint8_t *memblock;
  int fd;
  struct stat sb;

  fd = open(filename, O_RDONLY);
  fstat(fd, &sb);
  uint64_t size = sb.st_size;

  memblock = mmap(NULL, size, PROT_READ, MAP_SHARED | (populate ? MAP_POPULATE : 0), fd, 0);

  if (memblock == MAP_FAILED) {
    perror("mmap failed");
    return EXIT_FAILURE;
  }

  //printf("Opened %s of size %lu bytes\n", filename, size);  

  uint64_t i;
  uint8_t result = 0;
  for (i = 0; i < size; i++) {
    result += memblock[i];
  }

  sink = result;

  puts("Press enter to exit...");
  getchar();

  return EXIT_SUCCESS;
}

私はこのようにします:

gcc -O2 -std=gnu99     mmap_test.c   -o mmap_test

ファイル名と、が渡されるかどうかを制御するpopulateor nopopulate1を渡します。終了する前にエンターを入力するのを待ちます(何かをチェックアウトする時間を与えます)。MAP_POPULATEmmap/proc/<pid>

ランダム データの 1 GB のテスト ファイルを使用しますが、実際には何でも使用できます。

dd bs=1MB count=1000 if=/dev/urandom of=/dev/shm/rand1g

MAP_POPULATEを使用すると、ページ キャッシュ内のファイルでメジャー フォールトがゼロになり、ページ フォールトが少数になることが予想されます。perf stat私は期待される結果を得る:

perf stat -e major-faults,minor-faults ./mmap_test /dev/shm/rand1g populate
Press enter to exit...

 Performance counter stats for './mmap_test /dev/shm/rand1g populate':

                 0      major-faults                                                
                45      minor-faults                                                

       1.323418217 seconds time elapsed

45 のエラーは、ランタイムとプロセスのオーバーヘッドから発生します (マッピングされたファイルのサイズには依存しません)。

ただし、/usr/bin/time最大 15,300 の軽微な障害が報告されます。

 /usr/bin/time ./mmap_test /dev/shm/rand1g populate
Press enter to exit...

0.05user 0.05system 0:00.54elapsed 20%CPU (0avgtext+0avgdata 977744maxresident)k
0inputs+0outputs (0major+15318minor)pagefaults 0swaps

同じ ~15,300 の軽微な障害が、topおよび を調べることによって報告され/proc/<pid>/statます。

を使用しない場合MAP_POPULATE、 を含むすべての方法で、perf stat最大 15,300 のページ フォールトが発生することに同意します。1,000,000,000 / 4096 / 16 = ~15,250つまり、1GB が 4K ページに分割され、カーネル機能 (「フォールトアラウンド」) によってさらに 16 分の 1 に削減されます。障害発生時のページ キャッシュ。

ここにいるのは誰?の文書化された動作に基づいて、MAP_POPULATEによって返される図perf statは正しいものです。1 回のmmap呼び出しで、マッピング全体のページ テーブルが既に取り込まれているため、これに触れたときに軽微な障害が発生することはありません。


1実際には、以外の populate文字列はとして機能しnopopulateます。

4

0 に答える 0