Назад | Перейти на главную страницу

Что может вызывать повторение mmap / munmap в результатах strace?

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

Вам может быть интересно это запрос функции для сигнала для сброса трассировки стека, который, по-видимому, будет вам сейчас очень полезен.

Другая возможность - добавить в приложение дополнительный код регистрации.