У меня есть приложение (node.js), которое иногда вызывает 100 % Использование процессора. Я подключился к процессу с помощью 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
...
Может ли кто-нибудь пролить свет на то, что здесь может происходить? Спасибо!
Все, что можно вывести из этих выходных данных, - это то, что приложение выделяет и освобождает память. Поэтому должны быть некоторые структуры данных, которые растут и сжимаются.
Это, к сожалению, мало что говорит о том, что происходит на более высоком уровне приложения.
Мы также можем сделать некоторые выводы о том, как реализация управления памятью в 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
Это выделяет 2 МБ адресного пространства. Затем освободите начало и конец этого адресного пространства и, наконец, выделите 1 МБ памяти для средней части выделенного адресного пространства.
Фактически, эти четыре вызова выделяют 1 МБ памяти с адресом, выровненным с кратностью 1 МБ. Итак, мы рассматриваем шаблон, который явно хочет выровнять адреса.
Последующие вызовы munmap
просто освобождают блоки размером 1 МБ, выделенные ранее. В частности, я заметил
munmap(0x336451500000, 1048576) = 0
, что освобождает блок размером 1 МБ, выделенный в приведенных выше четырех системных вызовах.
Вероятно, все это не то, что вы хотели знать. Но, к сожалению, именно это можно вывести из вывода strace
, так что вам придется искать другие способы найти информацию, которую вы действительно хотите знать.
Возможно, вам это интересно запрос функции для сигнала сброса трассировки стека, который, по-видимому, будет очень полезен для вас прямо сейчас.
Другая возможность - добавить дополнительный код ведения журнала в ваше приложение.