Есть ли способ ограничить память, которую может иметь ghci?

Я привык отлаживать свой код с помощью ghci. Часто происходит что-то вроде этого (не так очевидно, конечно):

ghci> let f@(_:x) = 0:1:zipWith(+)f x
ghci> length f

Затем какое-то время ничего не происходит, и если я не отреагирую достаточно быстро, ghci съест, возможно, 2 ГБ ОЗУ, что приведет к зависанию моей системы. Если уже слишком поздно, единственный способ решить эту проблему — [ALT] + [PRINT] + [K].

Мой вопрос: есть ли простой способ ограничить память, которую может потреблять ghci, скажем, до 1 ГБ? Если предел превышен, расчет должен быть прерван или ghci должен быть убит.


person fuz    schedule 22.09.2010    source источник
comment
См. также stackoverflow.com/questions/5716216/   -  person Don Stewart    schedule 23.04.2011


Ответы (2)


Независимый от платформы способ добиться этого — указать параметр -M как параметр on для среды выполнения Haskell, как показано ниже.

ghci +RTS -M1m

см. страницу документации GHC о том, как управлять RTS (система выполнения) для получения подробной информации.

Вывод ghci теперь выглядит так:

>ghci +RTS -M10m
GHCi, version 6.12.3: http://www.haskell.org/ghc/  :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Loading package ffi-1.0 ... linking ... done.
Prelude> let f@(_:x) = 0:1:zipWith(+)f x
Prelude> length f
Heap exhausted;
Current maximum heap size is 10485760 bytes (10 MB);
use `+RTS -M<size>' to increase it.
person Bas Bossink    schedule 22.09.2010
comment
Я только что создал псевдоним alias ghci='ghci +RTS -M500m -RTS' в ~/.bashrc, и теперь все в порядке. Большое тебе спасибо. - person fuz; 22.09.2010
comment
Я предполагаю, что вы могли бы также использовать свой файл .ghci? haskell.org/ghc/docs/ 7.2.1/html/users_guide/ghci-dot-files.html - person MatrixFrog; 25.11.2011
comment
На самом деле это не прерывается при достижении предела, так что это не решение. Кроме того, ghci по-прежнему использует больше памяти, чем указано. Например, у меня 4Gb оперативной памяти, я установил -M100m. Он говорит мне, что он установлен на 100Mb, что совершенно нормально, но когда я запускаю fib 100000, программа все еще почти зависает на моей машине. Он не полностью замораживает его, как раньше, но память почти заполнена, и подкачка заполняется, что приводит к большому количеству операций ввода-вывода, что делает систему непригодной для использования в течение двух или более минут. - person Zelphir Kaltstahl; 11.02.2016
comment
Сейчас я проверил это с length — в этом простом случае это работает. - person Zelphir Kaltstahl; 11.02.2016
comment
@Zelphir работает у меня с GHCi-8.0.1. Вероятно, ошибка, которая была исправлена. Вы можете установить его со стеком и создать псевдоним, например. alias ghci512="stack ghci --ghci-options '+RTS -M512m -RTS'". Если вы используете стек для проектов, я бы рекомендовал в любом случае придерживаться его ghci, чтобы не дублировать библиотеки и файловый кеш в ОЗУ. - person Hi-Angel; 02.10.2016
comment
Следует отметить, что размер кучи — не единственное, что может расти. GHC позволяет вам контролировать максимальный и рекомендуемый размер кучи, размер стека, а также область выделения сборщика мусора. - person Evi1M4chine; 08.10.2017

Запустить его под оболочкой с установленным ulimit -m довольно просто. Если вы хотите регулярно запускать с некоторым ограничением, вы можете создать скрипт-оболочку, который выполняет ulimit перед запуском ghci.

person hobbs    schedule 22.09.2010
comment
Это не работает. Я попробовал что-то вроде ulimit -m 102400, и он все еще потребляет память. - person fuz; 22.09.2010
comment
@hobbs @FUZxxl вы должны использовать ulimit -v, а не ulimit -m. Переключатель -m ограничивает физическую память, а нужно ограничивать виртуальную: физическая+своп. Я использую ulimit -v $(( (1024**2)*2 )) (zsh) с 4 ГБ ОЗУ + 5 ГБ подкачки, и это не зависает в системе. Это ограничивает объем памяти до 2 ГБ и может быть помещен в ~/.zshrc или ~/.bashrc. - person ZyX; 22.09.2010
comment
Спасибо. Я нахожу это менее полезным, так как впоследствии я не могу снова изменить значение в оболочке. (Только вниз...) - person fuz; 22.09.2010
comment
@FUZxxl Почему ты не можешь? У меня с этим проблем нет (или вы имели в виду, что с GHCi нельзя поменять?). Это может быть менее полезно, потому что, когда процессу не хватает памяти, он может поймать SEGV и аварийно завершить работу, но GHCi справляется с этим нормально. В zsh есть связанная с этим полезная функция: если какое-то приложение, которое изменяет настройки tty (например, vim), падает, вы получаете беспорядок на экране и некоторые клавиши не работают. Встроенный Zsh ttyctl с аргументом -f предотвратит это. - person ZyX; 22.09.2010
comment
Я имею в виду следующее: сначала я делаю что-то вроде ulimit -v 102400, затем — после ghci — хочу отменить: ulimit -v unlimited, но получаю ошибку разрешения. - person fuz; 22.09.2010
comment
@FUZxxl Могу предложить перейти на zsh: мне удалось воспроизвести вашу проблему, но только на bash. - person ZyX; 22.09.2010
comment
В bash вы можете использовать круглые скобки для создания подоболочки, поэтому это должно установить ulimit, который применяется только к ghci и снимается при выходе из подоболочки: $ (ulimit -v 1000000; ghci) - person cthulahoops; 23.09.2010
comment
Стоит отметить, что опция -v принимает килобайты. man ulimit почему-то ничего не говорит о юнитах. - person Hi-Angel; 15.08.2016