如何在OSX上获得内存使用率高的水印

时间:2014-02-06 00:06:26

标签: macos bash dtrace

我希望能够测试一些关于各种命令行实用程序的内存复杂性的猜测。

举一个简单的例子

grep pattern file

我想了解内存使用情况如何随pattern的大小和file的大小而变化。

对于时间复杂度,我会猜测,然后运行

time grep pattern file

在各种大小的输入上看看我的猜测是否在现实中得到证实,但我不知道如何为记忆做这件事。

一种可能性是启动作业并定期对内存使用进行采样的包装脚本,但这似乎不够优雅,不太可能提供真正的高水印。

我看过time -v建议,但我的机器上没有可用的标志(在OSX上运行bash)并且不知道在哪里可以找到支持它的版本。

我还看到在Linux上,这些信息可以通过proc文件系统获得,但同样,在我的上下文中我无法使用它。

我想知道dtrace是否可能是一个合适的工具,但我又担心一个简单的基于样本的数字可能不是真正的高水印?

有没有人知道适合OSX的工具或方法?

修改

我删除了两个提及磁盘使用的内容,这些内容只是旁白,可能会分散问题的主要内容。

3 个答案:

答案 0 :(得分:3)

您的问题很有趣,因为如果没有应用程序源代码,您需要对内存使用的构成做一些假设。即使您使用procfs,结果也会产生误导:驻留集大小和总虚拟地址空间都将被高估,因为它们将包含无关数据,例如程序文本。

特别是对于小命令,跟踪单个分配会更容易,但即使在那里,您也需要确保包含所有可能的来源。除malloc()之外,进程可以使用brk()扩展其堆,或使用mmap()获取匿名内存。

这是跟踪malloc()的DTrace脚本;你可以扩展它以包括其他分配功能。请注意,它不适用于多线程程序,因为它使用了一些非原子变量。

bash-3.2# cat hwm.d
/* find the maximum outstanding allocation provided by malloc() */
size_t total, high;

pid$target::malloc:entry
{
    self->size = arg0;
}

pid$target::malloc:return
/arg1/
{
    total += self->size;
    allocation[arg1] = self->size;
    high = (total > high) ? total : high;
}

pid$target::free:entry
/allocation[arg0]/
{
    total -= allocation[arg0];
    allocation[arg0] = 0;
}

END
{
    printf("High water mark was %d bytes.\n", high);
}
bash-3.2# dtrace -x evaltime=exec -qs hwm.d -c 'grep maximum hwm.d'
/* find the maximum outstanding allocation provided by malloc() */
High water mark was 62485 bytes.

bash-3.2#

this article by Brendan Gregg中包含有关内存分配器的更全面的讨论。它为你的问题提供了比我自己更好的答案。特别是,它包含一个名为memleak.d的脚本的链接;修改此项以包括分配的时间戳&解除分配,以便您可以按时间对其输出进行排序。然后,也许使用附带的脚本作为示例,使用perl来跟踪当前未完成的总分配和高水位线。这样的DTrace / perl组合适用于跟踪多线程进程。

答案 1 :(得分:1)

您可以使用/usr/bin/time -l(不是macOS中内置的time的{​​em>不是),并读取“最大居民集大小”,这并不是精确的高水位线,而是可能会给您一些想法。

$ /usr/bin/time -l ls
...
        0.00 real         0.00 user         0.00 sys
    925696  maximum resident set size
         0  average shared memory size
         0  average unshared data size
         0  average unshared stack size
       239  page reclaims
         0  page faults
         0  swaps
         0  block input operations
         0  block output operations
         0  messages sent
         0  messages received
         0  signals received
         3  voluntary context switches
         1  involuntary context switches

此字段的含义在here中进行了说明。

答案 2 :(得分:0)

尝试了getrusage()。结果不正确。尝试过的乐器。痛苦不已。

迄今为止最好的解决方案:valgrind + massif

  • 基于命令行:易于运行,脚本化和自动化;没有要打开的应用程序,没有要单击的菜单,等等;可以在后台运行
  • 在终端中提供随时间变化的内存使用情况的直观图
    valgrind --tool=massif /path/to/my_program arg1 ...
    ms_print `ls -r massif.out.* | head -1` | grep Detailed -B50

要查看更多详细信息,请运行ms_print `ls -r massif.out.* | head -1`