mmap領域のシーケンシャル/ランダム読み取りで奇数の主要ページエラーが発生します。

mmap領域のシーケンシャル/ランダム読み取りで奇数の主要ページエラーが発生します。

私はフォローアップをしています。この回答、以下を使用していくつかの主要なページエラーを生成してみてくださいmmap

#include <fcntl.h>
#include <stdio.h>
#include <sys/mman.h>
#include <sys/stat.h>

int main(int argc, char ** argv) {
  int fd = open(argv[1], O_RDONLY);
  struct stat stats;
  fstat(fd, &stats);
  posix_fadvise(fd, 0, stats.st_size, POSIX_FADV_DONTNEED);
  char * map = (char *) mmap(NULL, stats.st_size, PROT_READ, MAP_SHARED, fd, 0);
  if (map == MAP_FAILED) {
    perror("Failed to mmap");
    return 1;
  }
  int result = 0;
  int i;
  for (i = 0; i < stats.st_size; i++) {
    result += map[i];
  }
  munmap(map, stats.st_size);
  return result;
}

1.6Gファイルをマップしてから読み取ろうとしましたが、メイン1ページエラーが発生しました。

Major (requiring I/O) page faults: 1
Minor (reclaiming a frame) page faults: 38139

ランダムにデータを読み取るとき

// hopefully this won't trigger extra page faults
unsigned int idx = 0;
for (i = 0; i < stats.st_size; i++) {
  result += map[idx % stats.st_size];
  idx += i;
}

ページエラーが急増しました。16415

Major (requiring I/O) page faults: 16415
Minor (reclaiming a frame) page faults: 37665

データをプリロードするためにカーネルに事前にインポートするのと同じことがありますかmmap/usr/bin/timeORでこれをどのように知ることができますかperf

私はgcc 6.5.0andを使っています。Ubuntu 18.044.15.0-54-generic

答え1

はい、カーネルはデフォルトで先読み(プリフェッチと呼ばれます)を実行します。https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/mm/filemap.c?h=v5.5#n2476

posix_madvise()mmap()afterを呼び出してアドバイスを提供することで、このメモリ領域への先読みを無効にできますPOSIX_MADV_RANDOM

関連情報