2010-06-01 2 views
4

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

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

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

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

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

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

ответ

3

У меня есть ответ на вопрос, который я задал.

Применение памяти Распределители:

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++ filt для демонстрации имен символов C++. (Утилита C++ filt предоставляется с помощью программного обеспечения Sun Studio.) Фильтрация через C++-фильтра не требуется, если приложение не является 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 allocator заключается в использовании улучшенного распределителя памяти, такого как библиотека libumem.

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

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

Смежные вопросы