我有一个 (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
,因此您必须寻找其他方法来找到您真正想知道的信息。
你可能对此感兴趣功能要求用于转储堆栈跟踪的信号,这可能对您现在非常有用。
另一种可能性是向您的应用程序添加更多的日志代码。