Это на самом деле дополнительный вопрос этого вопроса.Мне удалось заставить профилирование работать, и проблема действительно кажется ленивой.
Используемая мной структура данных: Map Int (Map Int Text)
, где Text
из Data.Text .Проблема в том, что функция, которая строит эту карту, создает огромный поток.Работая с вводимым текстом размером около 3 МБ, программам требуется более 250 МБ памяти.
Теперь для реальной цели этого вопроса:
Чтобы получить количество символов в этой структуре данныхэто использовать следующую функцию:
type TextResource = M.Map Int (M.Map Int T.Text)
totalSize :: TextResouce -> Int
totalSize = M.fold ((+) . (M.fold ((+). T.length) 0)) 0
Не красиво, но он выполняет свою работу.Я использую эту функцию в основной функции сразу после создания TextResource.Интересно то, что когда я профилирую программу, используя опцию RTS -hr
или -hc
, через некоторое время использование памяти уменьшается до 70 или 50 МБ, что было бы вполне нормально.
К сожалениюэто работает только при использовании параметров профилирования и функции totalSize
- без них он возвращается к 250 МБ.
Я загрузил программу (<70 строк) вместе с тестовым файлом и кабальным файлом, так чтоВы можете попробовать сами: <a href="http://www.file-upload.net/download-3623479/leak.zip.html" rel="nofollow noreferrer"> Ссылка
test.xml - это сгенерированный XML-файл, который следует поместить в каталог исполняемых файлов.Для сборки достаточно cabal configure --enable-executable-profiling
, а затем cabal build
(если у вас установлены профилирующие версии необходимых библиотек).
Вы можете увидеть изменения при запуске программы один раз с +RTS -hc
и один раз без.
Было бы здорово, если бы кто-то мог запустить программу, так как я действительно застрял здесь,Я уже пытался вставить deepseq
в нескольких местах, но ничего не работает (ну, кроме использования параметров профилирования).
Редактировать:
Профилирование показывает, однако, что используется только ~ 20 МБ кучи, поэтому, как в моем комментарии, я обвиняю GHC в том, что неосвобождая столько памяти ГК, сколько вы, кажется, хотите.
Спасибо, это указало мне правильное направление.Как выяснилось, вы можете сказать GHC выполнить сборку мусора ( executeGC ), которая прекрасно работает после глубокого изучения карты.Несмотря на то, что я полагаю, что использование executeGC не рекомендуется, это, кажется, правильный инструмент для работы здесь.
Edit2: Вот как я изменил основную функцию (+ глубокий поисквозврат buildTextFile):
main = do tf <- buildTextFile "test.xml"
performGC
putStrLn . show . text 1 1000 $ tf
getLine
putStrLn . show . text 100 1000 $ tf
return ()