Я анализирую несколько довольно больших XML-файлов с потоковым интерфейсом xml-проводника https://hackage.haskell.org/package/xml-conduit-1.8.0/docs/Text-XML-Stream-Parse.html#v:parseBytes, но я вижу это наращивание памяти (здесь в небольшом тестовом файле):
![heap use over time](https://i.stack.imgur.com/wMeL9.png)
, где топ-пользователи:
![heap blame](https://i.stack.imgur.com/F3o6e.png)
Фактические данные не должны занимать столько кучи- если я сериализую и перечитываю, резидентное использование памяти будет здесь в килобайтах по сравнению с мегабайтами.
Минимальный пример, который мне удалось воспроизвести:
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE OverloadedStrings #-}
module Main where
import Control.Monad
import Control.Monad.IO.Class
import Data.Conduit
import Data.Conduit.Binary (sourceFile)
import qualified Data.Conduit.List as CL
import Data.Text (Text)
import Text.XML.Stream.Parse
type Y = [(Text, Text)]
main :: IO ()
main = do
res1 <- runConduitRes $
sourceFile "test.xml"
.| Text.XML.Stream.Parse.parseBytes def
.| parseMain
.| CL.foldM get []
print res1
get :: (MonadIO m, Show a) => [a] -> [a] -> m [a]
get acc !vals = do
liftIO $! print vals -- this oughta force it?
return $! take 1 vals ++ acc
parseMain = void $ tagIgnoreAttrs "Period" parseDetails
parseDetails = many parseParam >>= yield
parseParam = tag' "param" parseParamAttrs $ \idAttr -> do
value <- content
return (idAttr, value)
parseParamAttrs = do
idAttr <- requireAttr "id"
attr "name"
return idAttr