У меня есть приложение (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
вывод, поэтому вам придется искать другие способы найти информацию, которую вы действительно хотите знать.
Вам может быть интересно это запрос функции для сигнала для сброса трассировки стека, который, по-видимому, будет вам сейчас очень полезен.
Другая возможность - добавить в приложение дополнительный код регистрации.