Использование pmap и gdb для поиска собственной утечки памяти

Я отлаживаю утечку собственной памяти в приложении Java. RSS растет на 1 ГБ в день, в то время как куча не увеличивается. Сравнивая выходные данные pmap с течением времени, я вижу, что несколько анонимных блоков добавляются либо в начало кучи, либо между двумя нативными библиотеками.

 Address           Kbytes     RSS   Dirty Mode  Mapping
0000000000400000       4       4       0 r-x-- java
0000000000601000       4       4       4 rw--- java
00000000008fc000   64156   64028   64028 rw---   [ anon ]
00000006c0000000 2467840 2466824 2466824 rw---   [ anon ] (heap)
0000000756a00000 2775040       0       0 -----   [ anon ]
0000000800000000   39808   39636   39636 rw---   [ anon ]
00000008026e0000  607360       0       0 -----   [ anon ]
00007fc8f0000000   11268   10944   10944 rw---   [ anon ]
00007fc8f0b01000   54268       0       0 -----   [ anon ]
00007fc938000000   49204   46164   46164 rw---   [ anon ]
00007fc93b00d000   16332       0       0 -----   [ anon ]
00007fc940000000  126784  126784  126784 rw---   [ anon ] 
00007fc947bd0000    4288       0       0 -----   [ anon ]
00007fc948000000   65512   65512   65512 rw---   [ anon ]
.....a lot of new anon blocks with memory 1012 and also ~64MB block shown in screenshot
00007fc98c448000      16      12       0 r-x-- sssd_pac_plugin.so
.....anon blocks with memormy increased over time:
00007fca747fe000    2044       0       0 ----- librmi.so
.....anon blocks with memormy increased over time:
00007fcb58015000      44      32       0 r-x-- libkrb5support.so.0.1
.............................................other libraries
00007fcbad8f8000       4       4       4 rw--- libnio.so
.....anon blocks with memormy increased over time like :
00007fcbb0000000   65420   65404   65404 rw---   [ anon ]
00007fcbc4f7e000    4820    4820    4820 rw---   [ anon ]
00007fcbc5433000    5420       0       0 -----   [ anon ]
00007fcbc597e000   90112   88172   88172 rwx--   [ anon ]
.....anon blocks with memormy increased over time
00007fcbd96ea000      44      16       0 r-x-- libjimage.so
...............................................other libraries
00007fcbdcdd9000       4       4       4 r---- ld-2.17.so
00007fcbdcdda000       4       4       4 rw--- ld-2.17.so
00007fcbdcddb000       4       4       4 rw---   [ anon ]
00007ffdbd52c000     140      40      40 rw---   [ stack ]
00007ffdbd578000       8       8       0 r-x--   [ anon ]
ffffffffff600000       4       0       0 r-x--   [ anon ]
---------------- ------- ------- ------- 
total kB         16585920 9216360 9206356
  1. Могу ли я сказать, что увеличение памяти между, скажем, sssd_pac_plugin.so и librmi.so связано с одним из них? Является ли это распределение памяти непрерывным? https://i.stack.imgur.com/G1duY.jpg

  2. В верхней части кучи создается много новых блоков памяти размером от 126 МБ до 1 МБ (100 небольших блоков по 1 МБ для справки) (адрес: 00007fc940000000 и выше). Означают ли они некоторую утечку памяти или просто создаются для каждого нового потока.

введите здесь описание изображения

  1. Чтобы увидеть данные в этих блоках, я попробовал приведенный ниже фрагмент, но я всегда не получаю от него строк. Это все в двоичном формате, который я не могу интерпретировать. Есть ли способ преобразовать его в строки? Или сопоставьте любой поток/библиотеку или что-нибудь, с чем я могу работать.
gdb -pid <pid>
dump memory mem.bin 0x00007fc940000000  0x00007fc940000000+126784  
#read file as:
strings mem.bin

Еще одно наблюдение заключается в том, что многие новые блоки и старые блоки увеличиваются примерно до 60-65 МБ. Количество этих блоков со временем сильно увеличивается. Наибольший вклад в увеличение RSS. https://i.stack.imgur.com/xueC8.png https://i.stack.imgur.com/hwbAb.jpg

Я также пробовал libtcmalloc и профилировщики, основная проблема заключается в производственной среде, где я не могу их использовать. В экземпляре dev утечка не так значительна, поэтому выходные данные профилировщика не могут быть проверены.


person Lakshya Sharma    schedule 02.04.2020    source источник
comment
Любые выводы/ответы на любой вопрос приветствуются.   -  person Lakshya Sharma    schedule 03.04.2020
comment
bro-code.in/2020/04/17 /debug-java-native-memory-leaks В нем много деталей, которые я уже пробовал   -  person Lakshya Sharma    schedule 04.02.2021


Ответы (1)


Очень простой подход: вы можете попробовать посмотреть, кто звонит mmap (а не munmap).

  • прикрепить к процессу
  • установить точку останова на mmap с командами для печати аргументов и обратной трассировки (возможно, 5 кадров) и продолжить
  • аналогичная вещь для munmap
  • перенаправить вывод
  • пусть поработает день
  • отделить
  • сопоставить mmaps с munmaps в выводе

Когда pmap периодически запускается сбоку, вы можете сопоставлять более новые анон-регионы с mmap обратными трассировками (возможно, вам придется поиграться с количеством кадров).


Уже есть эта приятная небольшая статья LINUX GDB: ИДЕНТИФИКАЦИЯ УТЕЧКИ ПАМЯТИ для начала.

Примечание:

  • вы ищете mmap и munmap, а не malloc и free
  • вам нужно будет узнать смещение возврата от mmap
  • Я не пробовал сценарий из статьи, но думаю, что он сделает то, что утверждает статья.

Поиск смещения инструкции возврата mmap (от начала mmap): просто запустите gdb с любым исполняемым файлом на том же хосте.

[ aquila ~ ] $ gdb -q /usr/bin/ls
Reading symbols from /usr/bin/ls...Reading symbols from /usr/bin/ls...(no debugging symbols found)...done
.
(no debugging symbols found)...done.
Missing separate debuginfos, use: dnf debuginfo-install coreutils-8.27-5.fc26.x86_64
(gdb) set pagination off
(gdb) set breakpoint pending on
(gdb) b mmap
Function "mmap" not defined.
Breakpoint 1 (mmap) pending.
(gdb) r
Starting program: /usr/bin/ls

Breakpoint 1, 0x00007ffff7df2940 in mmap64 () from /lib64/ld-linux-x86-64.so.2
(gdb) disassemble
Dump of assembler code for function mmap64:
=> 0x00007ffff7df2940 <+0>:     test   %rdi,%rdi
   0x00007ffff7df2943 <+3>:     push   %r15
   0x00007ffff7df2945 <+5>:     mov    %r9,%r15
    :
    :
   0x00007ffff7df2973 <+51>:    mov    $0x9,%eax
    :
   0x00007ffff7df2982 <+66>:    pop    %rbx
    :
   0x00007ffff7df298a <+74>:    pop    %r15
   0x00007ffff7df298c <+76>:    retq
   0x00007ffff7df298d <+77>:    nopl   (%rax)
    :
    :
   0x00007ffff7df29d8 <+152>:   mov    $0xffffffffffffffff,%rax
   0x00007ffff7df29df <+159>:   jmp    0x7ffff7df2982 <mmap64+66>
End of assembler dump.

Обратите внимание на инструкцию возврата здесь:

0x00007ffff7df298c <+76>:    retq

Итак, на моей машине вторая точка останова должна быть установлена ​​на (mmap+76).

Как только вы определите это смещение, вы можете проверить это смещение, подключившись к целевому процессу и разобрав то, что находится по этому смещению. Например. используя мою текущую оболочку в качестве целевого процесса:

[ aquila ~ ] $ echo $$
9769
[ aquila ~ ] $ gdb -q
(gdb) attach 9769
Attaching to process 9769
Reading symbols from /usr/bin/bash...Reading symbols from /usr/bin/bash...(no debugging symbols found)..
.done.
(no debugging symbols found)...done.
Reading symbols from /lib64/libtinfo.so.6...Reading symbols from /lib64/libtinfo.so.6...(no debugging sy
mbols found)...done.
(no debugging symbols found)...done.
Reading symbols from /lib64/libdl.so.2...(no debugging symbols found)...done.
Reading symbols from /lib64/libc.so.6...(no debugging symbols found)...done.
Reading symbols from /lib64/ld-linux-x86-64.so.2...(no debugging symbols found)...done.
Reading symbols from /lib64/libnss_files.so.2...(no debugging symbols found)...done.
0x00007fcfc67cc18a in waitpid () from /lib64/libc.so.6
Missing separate debuginfos, use: dnf debuginfo-install bash-4.4.12-5.fc26.x86_64
(gdb) x/i mmap+76
   0x7fcfc680375c <mmap64+76>:  retq

Я не очень уверен, что hbreak требуется, старый добрый break тоже может подойти.

person ranga    schedule 05.04.2020
comment
Можете ли вы помочь установить точку останова и распечатать аргументы в gdb. извините новичок в этом. Ссылка будет делать - person Lakshya Sharma; 06.04.2020
comment
хорошо, тогда, может быть, вы примете этот ответ как решение? - person ranga; 13.04.2020
comment
будет включать его, и если нет икоты, он отметит его принятым, и в нем также есть несколько других вопросов. будет ждать некоторое время для любого другого частичного ответа - person Lakshya Sharma; 13.04.2020
comment
bro-code.in/2020/04/17 /debug-java-native-memory-leaks - person Lakshya Sharma; 04.02.2021