Археологические раскопки ядра vista-longhorn

Менеджер кучи


Динамическая память, так же называемая кучей (без которой немыслимо существование приплюснутого си и платформы .NET) облагает программиста ощутимыми накладными расходами, особенно заметными на маленьких блоках, однако, оптимизация менажера кучи _не_ способна ощутимо повлиять на производительность, поскольку выделение маленьких блоков берет на себя библиотека времени исполнения (RTL) конкретного компилятора, обращающаяся к операционной системе только с "оптовыми" заказами.

Если отбросить улучшения, касающееся многопроцессорных систем, виста отличается от XP только уменьшенной фрагментацией кучи (the low-fragmentation heap— LFH), эвристическими алгоритмами, автоматически подстраивающимися под характер запрос на выделение памяти и отложенной (lazy) инициализацией.

Насчет фрагментации — это откровенное вранье. Фрагментация кучи приводит отнюдь не к падению производительности, а к невозможности выделения непрерывного блока требуемых размеров, хотя по "кускам" свободной памяти может быть в сотни раз больше. Приложение просто отказывает в работе, показывая какой лось его создатель. С нормальными программами такого не случается. У них другая проблема — утечки памяти. Ошибки проектирования приводят к тому, что выделенная однажды память не освобождается, образуя мощные "осадочные" пласты, наслаивающиеся друг на друга вплоть до полного исчерпания всей свободной памяти, завершающегося падением приложения. Справиться с утечками операционная система к сожалению не в силах, поскольку не существует никаких признаков, позволяющих отличить полезный блок от блока который забыли освободить. Что же касается адаптивных алгоритмов, то всегда существует угроза, что они сработают с точностью до наоборот, и вместо обещанного выигрыша (составляющего от силы десятки процентов) мы получим грандиозное падение производительности.

Тоже самое относится и к переписанному lookup-алгоритму (на котором базируются функции выделения и освобождения памяти), теперь его эффективность составляет не O(n), а O(1), то есть время поиска представляет собой константу, не зависящую ни от каких внешних факторов (например, количества выделенных блоков). Как это влияет на производительность? А вот как! У нас есть два ящика. Один черный, другой прозрачный и в нем лежит $100. Какой из ящиков содержит больше денег? Вот-вот, так же и здесь! O(n) – это линейная зависимость, представляющая собой наклонную кривую, O(1) — это прямая, параллельная оси OX. В точке пересечения двух прямых (которая из условий задачи нам _не_ известна) эффективность обоих алгоритмов совпадает, после чего алгоритм O(1) начинает давать все больший и больший выигрыш, чем O(n), однако, по левую сторону от точки пересечения все не так и там выгоднее O(n). Но это в теории. На практике, опять-таки, наибольшее влияние на производительность оказывает именно RTL, то есть библиотека времени исполнения, поставляемая вместе с компилятором…

Рисунок 3 куча — как она есть в висте



Содержание раздела