什么可能导致 strace 结果中重复出现 mmap/munmap?

什么可能导致 strace 结果中重复出现 mmap/munmap?

我有一个 (node.js) 应用程序,它偶尔会导致 100% 的 CPU 使用率。当它处于这种状态时,我已经将其附加到该进程strace- 但我不知道如果 strace 输出该怎么做。结果在这两个模式之间重复(缩短):

mmap(0x30c3ac700000, 1048576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x30c3ac700000
mmap(0x3364514ba000, 2097152, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0) = 0x3364514ba000
munmap(0x3364514ba000, 286720)          = 0
munmap(0x336451600000, 761856)          = 0
mmap(0x336451500000, 1048576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x336451500000
mmap(0x2b9c33880000, 2097152, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0) = 0x2b9c33880000
munmap(0x2b9c33880000, 524288)          = 0
munmap(0x2b9c33a00000, 524288)          = 0
...

和...

munmap(0x2b9c33900000, 1048576)         = 0
munmap(0x336451500000, 1048576)         = 0
munmap(0x30c3ac700000, 1048576)         = 0
munmap(0x247e37500000, 1048576)         = 0
munmap(0x20d76c800000, 1048576)         = 0
munmap(0x1cae0d600000, 1048576)         = 0
munmap(0x163545100000, 1048576)         = 0
munmap(0x32dcfe700000, 1048576)         = 0
munmap(0x1a1feff00000, 1048576)         = 0
munmap(0x3fb72f00000, 1048576)          = 0
munmap(0x366536900000, 1048576)         = 0
...

有人能解释一下这里发生了什么吗?谢谢!

答案1

从此输出可以推断出应用程序正在分配和释放内存。因此一定有一些数据结构在增长和收缩。

不幸的是,这并没有说明应用程序更高层发生的情况。

node.js由于的参数有两种不同的变化,我们还可以推断出中的内存管理实现是如何实现的mmap

PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE

这些参数分配了地址空间,但PROT_NONE意味着保留的地址空间不能使用(除非稍后的另一个调用使其可访问)。

PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS

这些参数为特定范围的地址分配实际内存(可能是先前使用其他参数组合分配的地址),并将其转变为读/写区域。

我们可以通过观察这四个系统调用的序列来猜测为什么会这样:

mmap(0x3364514ba000, 2097152, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0) = 0x3364514ba000
munmap(0x3364514ba000, 286720)          = 0
munmap(0x336451600000, 761856)          = 0
mmap(0x336451500000, 1048576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x336451500000

这将分配 2MB 的地址空间。然后释放该地址空间的起始和结束位置,最后为分配的地址空间的中间部分分配 1MB 的内存。

实际上,这四个调用分配了 1MB 内存,地址与 1MB 的倍数对齐。因此,我们看到的是一个明确需要对齐地址的模式。

后面的munmap调用只是释放之前分配的 1MB 块。我特别注意到

munmap(0x336451500000, 1048576)         = 0

这将释放上述四个系统调用中分配的 1MB 块。

所有这些可能都不是您想知道的。但不幸的是,这些可以从输出中推断出来strace,因此您必须寻找其他方法来找到您真正想知道的信息。

你可能对此感兴趣功能要求用于转储堆栈跟踪的信号,这可能对您现在非常有用。

另一种可能性是向您的应用程序添加更多的日志代码。

相关内容