Сегодня я попросил GHC скомпилировать исходный файл Haskell объемом 8 Мбайт. GHC думал об этом около 6 минут, проглотил почти 2 ГБ оперативной памяти, а затем, наконец, сдался с ошибкой из памяти.
[Как в сторону, я рад, что GHC имел здравый смысл прекратить, а не настил весь мой компьютер.]
В принципе, у меня есть программа, которая читает текстовый файл, делает какой-то причудливый синтаксический разбор, строит структуру данных и затем использует show
, чтобы сбрасывать это в файл. Вместо того, чтобы включать весь синтаксический анализатор и исходные данные в моем конечном приложении, я хотел бы включить сгенерированные данные в качестве константы времени компиляции. Добавив некоторые дополнительные данные к выводу из show
, вы можете сделать его действительным модулем Haskell. Но GHC, по-видимому, не любит компиляцию исходных файлов с несколькими MB.
(Самая странная часть - если вы только read
возвращаете данные, на самом деле это не занимает много времени или памяти. Странно, учитывая, что оба String
I/O и read
предположительно очень неэффективны...)
Я смутно помню, что у других людей были проблемы с получением GHC для сбора огромных файлов в прошлом. FWIW, я попытался использовать -O0
, что ускорило крушение, но не помешало ему. Итак, каков наилучший способ включения больших констант времени компиляции в программу Haskell?
(В моем случае константа является всего лишь вложенным Data.Map
с некоторыми интересными метками.)
Первоначально я думал, что GHC может быть просто недовольна чтением модуля, состоящего из одной строки длиной восемь миллионов символов. (!!) Что-то делать с правилом макета или таким. Или возможно, что глубоко вложенные выражения нарушают его. Но я попытался сделать каждое подвыражение идентификатором верхнего уровня, и это не помогло. (Добавление явных сигнатур типов к каждому из них, похоже, сделало компилятор немного более счастливым.) Есть ли что-нибудь еще, что я мог бы попытаться сделать компилятор проще?
В конце концов, мне удалось создать структуру данных, которую я на самом деле пытаюсь сохранить намного меньше. (Например, 300 КБ.) Это сделало GHC намного более счастливым. (И последнее приложение намного быстрее.) Но для будущей ссылки мне было бы интересно узнать, как лучше всего подойти к этому.