Освобождение выделенной памяти в Solaris / Linux - PullRequest
4 голосов
/ 01 июня 2010

Я написал небольшую программу и скомпилировал ее на платформе Solaris / Linux, чтобы измерить производительность применения этого кода в моем приложении.

Программа написана таким образом, изначально используя системный вызов sbrk(0), я взял базовый адрес области кучи. После этого я выделил 1,5 ГБ памяти с помощью системного вызова malloc. Затем я использовал системный вызов memcpy, чтобы скопировать 1,5 ГБ содержимого в выделенную область памяти. Затем я освободил выделенную память.

После освобождения я снова использовал системный вызов sbrk(0) для просмотра размера кучи.

Здесь я немного запутался. В Solaris, хотя я освободил выделенную память (почти 1,5 ГБ), размер кучи процесса огромен. Но я запускаю то же самое приложение в Linux, после освобождения обнаружил, что размер кучи процесса равен размеру кучи памяти до выделения 1,5 ГБ.

Я знаю, что Solaris не освобождает память сразу, но я не знаю, как настроить ядро ​​Solaris для немедленного освобождения памяти после системного вызова free().

Почему у меня нет такой же проблемы под Linux?

1 Ответ

3 голосов
/ 03 июня 2010

Я получил ответ на вопрос, который я задал.

Распределители памяти приложений:

Разработчики C и C ++ должны вручную управлять распределением памяти и свободной памятью. Распределитель памяти по умолчанию находится в библиотеке libc.

Libc Обратите внимание, что после выполнения free () освободившееся пространство становится доступным для дальнейшего распределения приложением и не возвращается в систему. Память возвращается в систему только после завершения работы приложения. Вот почему размер процесса приложения обычно никогда не уменьшается. Но для долго работающего приложения размер процесса приложения обычно остается в стабильном состоянии, поскольку освобожденная память может использоваться повторно. Если это не так, то, скорее всего, у приложения есть утечка памяти, то есть выделенная память используется, но никогда не освобождается, когда она больше не используется, а указатель на выделенную память не отслеживается приложением - в основном теряется.

Распределитель памяти по умолчанию в libc не подходит для многопоточных приложений, когда часто происходят параллельные malloc или свободные операции, особенно для многопоточных приложений C ++. Это связано с тем, что создание и уничтожение объектов C ++ является частью стиля разработки приложений C ++. Когда используется распределитель libc по умолчанию, куча защищена одной блокировкой кучи, в результате чего распределитель по умолчанию не масштабируется для многопоточных приложений из-за серьезных конфликтов блокировок во время malloc или свободных операций. С помощью инструментов Solaris легко обнаружить эту проблему следующим образом.

Во-первых, используйте prstat -mL -p, чтобы узнать, тратит ли приложение много времени на блокировки; посмотрите на колонку LCK. Например:

-bash-3.2# prstat -mL -p 14052
   PID USERNAME USR SYS TRP TFL DFL LCK SLP LAT VCX ICX SCL SIG PROCESS/LWPID
 14052 root     0.6 0.7 0.0 0.0 0.0  35 0.0  64 245  13 841   0 test_vector_/721
 14052 root     1.0 0.0 0.0 0.0 0.0  35 0.0  64 287   5 731   0 test_vector_/941
 14052 root     1.0 0.0 0.0 0.0 0.0  35 0.0  64 298   3 680   0 test_vector_/181
 14052 root     1.0 0.1 0.0 0.0 0.0  35 0.0  64 298   3  1K   0 test_vector_/549
 ....

Это показывает, что приложение тратит около 35 процентов своего времени на ожидание блокировки.

Затем, используя инструмент plockstat (1M), найдите, какие блокировки ожидает приложение. Например, проследите за приложением в течение 5 секунд с идентификатором процесса 14052, а затем отфильтруйте выходные данные с помощью утилиты фильтра c ++ для определения имен символов C ++. (Утилита c ++ Filter поставляется с программным обеспечением Sun Studio.) Фильтрация через C ++ Filter не требуется, если приложение не является приложением C ++.

-bash-3.2#  plockstat -e 5 -p 14052 | c++filt
Mutex block
Count     nsec   Lock                         Caller
-------------------------------------------------------------------------------
 9678 166540561 libc.so.1‘libc_malloc_lock   libCrun.so.1‘void operator 
 delete(void*)+0x26

 5530 197179848 libc.so.1‘libc_malloc_lock   libCrun.so.1‘void*operator 
 new(unsigned)+0x38

......

Из предыдущего вы можете видеть, что блокировка кучи libc_malloc_lock активно используется и является вероятной причиной проблемы масштабирования. Решение этой проблемы масштабирования распределителя libc заключается в использовании улучшенного распределителя памяти, такого как библиотека libumem.

Также посетите: http://developers.sun.com/solaris/articles/solaris_memory.html

Спасибо всем, кто пытался ответить на мой вопрос, Сантош.

...