Подтвердить что ты не робот

В долгосрочной перспективе приложение Common Lisp, какую стратегию следует использовать для управления мусором?

Если я размещаю долгое приложение, такое как веб-сервер в общем изображении Lisp, какую стратегию я должен использовать для управления сборщиком мусора?

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

Есть ли способ в Common Lisp для управления этим? Возможно, поощряя его работать "мало-часто"?

4b9b3361

Ответ 1

В нескольких реализациях Lisp есть отличные сборщики мусора. Особой проблемой является то, что приложения Lisp часто имеют высокую скорость выделения небольших объектов (conses,...).

Есть несколько вещей, которые следует учитывать.

  • Точный против консервативного GC. Я не большой поклонник консервативных GC (Boehm и т.д.) Для Lisp. Проблема консервативных GC заключается в том, что они не находят все мусора. Это может быть проблемой для длительных программ и привести к фрагментации, а не к восстановленной неиспользуемой памяти. Точные GC используют информацию тега из данных Lisp и могут идентифицировать каждый тип данных для каждого объекта. Консервативные GC были изобретены для программирования языковых реализаций, которые не используют помеченные данные (С++,...).

  • копирование GC, уплотнение GC. Для работы с фрагментацией памяти в длинных Lisps может оказаться полезным GC, который объединяет и локализует объекты. Иногда возникает проблема, когда хэш-таблицы нужно перерисовывать (потому что местоположение меняется). Для копирования GC может потребоваться больше памяти (потому что есть и от пространства памяти). Но когда GC копирует объекты из одного пространства памяти в другое, он автоматически делает его более компактным. Более продвинутые GC (например, на машине Lisp) также могут сортировать объекты и выделять объекты одного типа рядом друг с другом - при условии, что это ускорит доступ к объектам.

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

  • генерация GC. Обычно GCs в настоящее время являются поколением. Существует более одного поколения, и объекты, которые выдержали несколько GC, продвигаются в более старшее поколение. Обычно только первое поколение GCed очень часто.

  • Настройка. ГК, скажем, LispWorks и Allegro CL, имеют множество регуляторов настройки. Специально для длительных приложений имеет смысл прочитать руководство и, например, настроить количество поколений, их размеры и другие вещи.

  • виртуальная память. GC поверх виртуальной памяти, как правило, очень медленный. Избегайте, если это возможно - добавьте больше ОЗУ в машины.

  • ручное управление памятью. Например, веб-сервер CL-HTTP выполняет ручное управление памятью с помощью ресурсов. Это пулы предварительно выделенных объектов, которые можно быстро инициализировать. Машины Lisp использовали это много. Типичное их использование - в буферах чтения для потоков. Вместо создания новых строк при каждой операции чтения полезно использовать повторно используемые буферы.

  • распределение стека. Некоторые Common Lisp позволяют распределять стеки некоторых данных - оставляя блок, затем автоматически освобождает память. Это предполагает, что память больше не ссылается при выходе из блока.

  • параллельный GC. Ни одна из обычных реализаций Common Lisp не имеет параллельной поддержки GC AND для параллельных потоков Lisp. Некоторые реализации имеют параллельные потоки Lisp, но GC остановит их все, пока он работает.

  • профилирование GC. Если вы не знаете, где происходит распределение и что делает GC, вам нужно найти это, используя информацию профилирования.

Если ваш Lisp имеет точный генератор GC, который работает в основной памяти, трудно получить проблемы с длинными паузами. Clozure CL (свободная реализация Common Lisp), например, имеет очень хорошую реализацию GC. Вы хотите избежать фрагментации памяти и сборки мусора в виртуальной памяти. При необходимости используйте 64-битную реализацию Lisp с большей памятью.

Указатели

Из документации видно, что LispWorks и Allegro CL имеют множество регуляторов для настройки GC.

Общие Lisp выполняет несколько функций, связанных с средой реализации. (ROOM) - это функция, которая дает обзор использования памяти. (ROOM t) дает более подробную информацию (здесь LispWorks):

CL-USER 2 > (room t)
 Generation 0:  Total Size 1823K, Allocated 1090K, Free 725K 
          Segment 2008AAB8: Total Size 507K, Allocated 361K, Free 142K
                    minimum free space 64K, 
                      Awaiting promotion = 0K, sweeps before promotion =10
          Segment 217E7050: Total Size 1315K, Allocated 729K, Free 582K
                    minimum free space 0K, 
                      Awaiting promotion = 0K, sweeps before promotion =2
 Generation 1:  Total Size 1397K, Allocated 513K, Free 871K 
          Segment 20CB9A50: Total Size 68K, Allocated 48K, Free 15K
                    minimum free space 0K, 
                      Awaiting promotion = 0K, sweeps before promotion =4
          Segment 216D7050: Total Size 1088K, Allocated 331K, Free 752K
                    minimum free space 0K, 
                      Awaiting promotion = 0K, sweeps before promotion =4
          Segment 2004E4F8: Total Size 241K, Allocated 133K, Free 103K
                    minimum free space 0K, static
 Generation 2:  Total Size 2884K, Allocated 1290K, Free 1585K 
          Segment 21417050: Total Size 2816K, Allocated 1227K, Free 1584K
                    minimum free space 0K, 
                      Awaiting promotion = 0K, sweeps before promotion =4
          Segment 20DA5DA0: Total Size 68K, Allocated 62K, Free 1K
                    minimum free space 117K, 
                      Awaiting promotion = 0K, sweeps before promotion =4
 Generation 3:  Total Size 19373K, Allocated 19232K, Free 128K 
          Segment 20109A50: Total Size 11968K, Allocated 11963K, Free 0K
                    minimum free space 3K, 
                      Awaiting promotion = 0K, sweeps before promotion =10
          Segment 20DB6E18: Total Size 6528K, Allocated 6396K, Free 128K
                    minimum free space 0K, 
                      Awaiting promotion = 0K, sweeps before promotion =10
          Segment 20CCAAC8: Total Size 876K, Allocated 872K, Free 0K
                    minimum free space 0K, 
                      Awaiting promotion = 0K, sweeps before promotion =10

Total Size 25792K, Allocated 22127K, Free 3310K

Ответ 2

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

Однако детали сбора мусора зависят от реализации. Существует не так много высококачественных реализаций Lisp, поэтому вам не составит труда консультироваться с их документацией по сбору мусора.