среда, 17 марта 2010 г.

Письма от наших телезрителей

Отвечая на вопрос ln_123
 
Кстати как человек копавшийся внутри sbcl скажите что он так память жрет? А то потребление больше в разы чем на других реализациях. Интересно с этим можно что нибудь сделать?
  1. Аллокатор выделяет память кусками, равными 16 байт. Т.е. если на самом деле нужна пара байт, то 14 байт теряется впустую. 
  2. Маленькие объекты (меньше размера страницы) на границе страниц не создаются. Остаток страницы выбрасывается. Т.е. если в странице занято 32 байта (свободно 4064 байта), и запрашивается память под объект размером 4080 байт, то эта страница вместе со всеми своими свободными байтами выбрасывается.
  3. Большие объекты (больше размера страницы) создаются исключительно в начале страницы (как в пункте 2). Остаток последней страницы, занятой хвостом большого объекта, выбрасывается.
  4. Указатель на свободную память движется только вперёд. Если 99% объектов, созданных до текущего указателя, уже умерли, то память не освобождается до следующего запуска сборщика мусора.
В итоге, в нормальных условиях (памяти хватает) выделение памяти под объект в SBCL супербыстрое: просто увеличивается указатель на свободную память.

3 комментария:

  1. Спасибо, очень интересно.
    А когда выполняется save-lisp-and-die вся память сбрасывается на диск без оптимизации?

    Что то мне подсказывает что довольно много памяти занимают объекты которые будут неизменны во время работы практически любой программы наверное во время сохранения можно было бы как то оптимизировать память под них.

    ОтветитьУдалить
  2. > А когда выполняется save-lisp-and-die вся память сбрасывается на диск без оптимизации?

    Сбрасываются только значащие страницы. Причём, адреса т.н. pinned страниц, которые при сборке мусора не перемещаются, в образе не сохраняются. Поэтому если сделать foreign-alloc, сохраниться, загрузиться, сделать foreign-free, то получится memory corrupt.

    > Что то мне подсказывает что довольно много памяти занимают объекты которые будут неизменны во время работы практически любой программы наверное во время сохранения можно было бы как то оптимизировать память под них.

    Да там особо оптимизировать нечего, не меняя принцип работы сборщика мусора. Сборщик полагает, что маленький объект лежит в одной странице, а большой объект лежит один в своих страницах. Соответственно, если менять эти два пункта, то логики наворачивать придётся сильно больше, плюс скорость сборщика колоссально упадёт. Лучше быстро, чем экономно. Экономные медленные лиспы у нас тоже есть ;)

    Менять 16-байтное выравнивание, наверное, тоже смысла нет. Хотя, попробую.

    ОтветитьУдалить
  3. А можно сделать так, при сохранении собрать маленькие объекты на страницах как можно более оптимальным образом?
    Т.е. имеем
    объект 1 32 байта, пустое место до конца страницы 4064 байта, объект 2 4080 байт, пустое место 16 байт, объект 3 4000 байт

    а после lisp-save получаем

    объект 1 32 байта, объект 3 4000 байт, пустое место 64 байта, объект 2 4064 байта

    Тогда ничего менять не придется а образ станет меньше. Правда время сохранения образа наверное существенно увеличиться :(

    Интересно а сколько имеется объектов меньше 16 байт в образе?

    ОтветитьУдалить

Архив блога