【问题标题】:Which (OS X) dtrace probe fires when a page is faulted in from disk?当页面从磁盘出现故障时,哪个(OS X)dtrace 探针会触发?
【发布时间】:2011-03-21 22:07:31
【问题描述】:

我正在编写一个关于页面错误的文档,并试图获得一些具体的数字来处理,所以我编写了一个简单的程序来读取 12*1024*1024 字节的数据。简单:

int main()
{
  FILE*in = fopen("data.bin", "rb");
  int i;
  int total=0;
  for(i=0; i<1024*1024*12; i++)
    total += fgetc(in);
  printf("%d\n", total);
}

所以是的,它会遍历并读取整个文件。问题是我需要在此过程中将触发 1536 次的 dtrace 探针(12M/8k)。即使我计算了所有 fbt:mach_kernel:vm_fault*: 探测器和所有 vminfo::: 探测器,我也没有达到 500,所以我知道我没有找到正确的探测器。

有谁知道我在哪里可以找到当一个页面从磁盘出现故障时触发的 dtrace 探测器?

更新:

如果问题在于 stdio 函数中正在进行一些智能预取,我尝试了以下操作:

int main()
{
  int in = open("data.bin", O_RDONLY | O_NONBLOCK);
  int i;
  int total=0;
  char buf[128];
  for(i=0; i<1024*1024*12; i++)
  {
    read(in, buf, 1);
    total += buf[0];
  }
  printf("%d\n", total);
}

这个版本需要更长的时间来运行(42 秒实时,其中 10 秒是用户时间,其余是系统时间 - 我猜是页面错误),但仍然会产生五分之一的错误,这是我预期的。

出于好奇,时间增加并不是由于循环开销和强制转换(char 到 int)。执行这些操作的代码版本需要 0.07 秒。

【问题讨论】:

  • ...以及后续问题...为什么 dtrace 问题总是以“唧唧喳喳的声音”类别结束?我怀疑这是因为 dtrace 探测的唯一真正文档位于内核源代码中,OS X 仅少量发布。这就是为什么我更喜欢在 Solaris 机器上使用 dtrace,这样我就可以从 Open Solaris 中挖掘出我需要的东西。
  • 你也可以在 FreeBSD 上试试dtrace :)

标签: virtual-memory dtrace probe page-fault


【解决方案1】:

不是一个直接的答案,但您似乎将磁盘读取和页面错误等同起来。它们不一定相同。在您的代码中,您正在将文件中的数据读取到一个小的用户内存块中,因此 I/O 系统可以以任何它认为合适的方式和大小将文件读取到缓冲区/VM 缓存中。我这里可能错了,我不知道达尔文是怎么做到的。

我认为更可靠的测试是将mmap(2)整个文件放入进程内存,然后去触摸每个页面就是那个空间。

【讨论】:

  • 为什么我假设读取会通过故障强制加载,我不知道。你已经死在 mmap 上了,我应该知道的更多。
【解决方案2】:

我最近也在同一个老鼠洞里。我现在没有可用的 DTrace 脚本或测试程序,但我会给你以下建议:

1.) 掌握 Amit Singh 的 OS X Internals 并阅读有关虚拟内存的第 8.3 节(这将使您进入选择 DTrace 探针的正确参考框架)。

2.) 亲身体验 Brendan Gregg / Jim Mauro 的 Solaris 性能和工具。阅读有关虚拟内存的部分,并密切关注使用 vminfo 提供程序的示例 DTrace 脚本。

3.) OS X 肯定会从文件系统中预取大量页面,并且您的测试程序正在使用这种优化(因为您是按顺序读取的)。有趣的是,Solaris 并非如此。尝试随机访问大数组以击败预取。

【讨论】:

    【解决方案3】:

    操作系统会在作为单独操作被触摸的每个页面中发生故障的假设(因此,如果您触摸 N 个页面,您将看到 DTrace 探测器触发 N 次)是有缺陷的;大多数 UN*Xes 将执行某种预读或预故障,并且您不太可能获得与页面完全相同数量的调用。即使您直接使用 mmap() 也是如此。

    确切的比率也可能取决于文件系统,因为预读和页面集群的实现和阈值不太可能对所有它们都相同。

    如果您直接使用 mmap,然后应用 madvise(MADV_DONTNEED) 或类似方法和/或使用 msync(MS_INVALIDATE) 清除整个范围,您可能可以强制执行每页错误策略。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-24
      • 1970-01-01
      • 2021-05-30
      • 1970-01-01
      • 2021-10-20
      • 1970-01-01
      相关资源
      最近更新 更多