52700.fb2
True, Nothing]:
nil
= []
true
= True
nothing = Nothing
let x1 = Just true
-- 2 слова
x2 = Just true
-- 2 слова
p1 = Cons nothing nil
-- 3 слова
p2 = Cons x2 p1
-- 3 слова
p3 = Cons x1 p2
-- 3 слова
in
p3
----------
-- 13 слов
Обычно одно слово соответствует 16, 32 или 64 битам. Эта цифра зависит от процессора. Мы считали,
что любое значение можно поместить в одно слово, но это не так. Возьмём к примеру действительные чис-
ла с двойной точностью, они не поместятся в одно слово. Это необходимо учитывать при оценке объёма
занимаемой памяти.
10.5 Управление памятью. Сборщик мусора
В прошлом разделе для простоты мы считали, что объекты только добавляются в кучу. На самом деле это
не так. Допустим во время вычисления функции нам нужно было вычислить какие-то промежуточные дан-
ные, например объявленные в локальных переменных, тогда после вычисления результата все эти значения
больше не нужны. При этом в куче висит много-много объектов, которые уже не нужны. Нам нужно как-то от
них избавится. Этой задачей занимается отдельный блок вычислителя, который называется сборщиком му-
сора (garbage collector), соответственно процесс автоматического освобождения памяти называется сборкой
мусора (garbage collection или GC).
На данный момент в GHC используется копирующий последовательный сборщик мусора, который рабо-
тает по алгоритму Чейни (Cheney). Для начала рассмотрим простой алгоритм сборки мусора. Мы выделяем
небольшой объём памяти и начинаем наполнять его объектами. Как только место кончится мы найдём все
“живые” объекты, а остальное пространство памяти будем считать свободным. Как только после очередной
очистки оказалось, что нам всё же не хватает места. Мы найдём все живые объекты, подсчитаем сколько ме-
ста они занимают и запросим у системы этот объём памяти. Скопируем все живые объекты на новое место, а
старую память будем считать свободной. Так например, если у нас было выделено 30 Мб памяти и оказалось,
что живые объекты занимают 10 Мб, мы выделим ещё 10 Мб, скопируем туда все живые объекты и общий
объём памяти станет равным 40 Мб.
Мы можем оптимизировать сборку мусора. Есть такая гипотеза, что большинство объектов имеют очень
короткую жизнь. Это промежуточные данные, локальные переменные. Нам нужен лишь результат функции,
но на подходе к результату мы сгенерируем много разовой информации. Ускорить очистку можно так. Мы
выделим совсем небольшой участок памяти внутри нашей кучи, его принято называть яслями (nursery area),
и будем выделять и собирать новые объекты только в нём, как только этот участок заполнится мы скопируем
все живые объекты из яслей в остальную память и снова будем наполнять ясли. Как только вся память закон-
чится мы поступим так же как и в предыдущем сценарии. Когда заканчивается место в яслях, мы проводим
поверхностную очистку (minor GC), а когда заканчивается вся память в текущей куче, мы проводим глубокую