Отладка проблем с производительностью HXT
Я пытаюсь использовать HXT для чтения больших файлов данных XML (сотни МБ).
У моего кода где- то есть утечка пространства, но я не могу его найти. Я немного разбираюсь в том, что происходит, благодаря моим очень ограниченным знаниям о цепочке инструментов профилирования ghc.
По сути, документ анализируется, но не оценивается.
Вот некоторый код:
{-# LANGUAGE Arrows, NoMonomorphismRestriction #-}
import Text.XML.HXT.Core
import System.Environment (getArgs)
import Control.Monad (liftM)
main = do file <- (liftM head getArgs) >>= parseTuba
case file of(Left m) -> print "Failed."
(Right _) -> print "Success."
data Sentence t = Sentence [Node t] deriving Show
data Node t = Word { wSurface :: !t } deriving Show
parseTuba :: FilePath -> IO (Either String ([Sentence String]))
parseTuba f = do r <- runX (readDocument [] f >>> process)
case r of
[] -> return $ Left "No parse result."
[pr] -> return $ Right pr
_ -> return $ Left "Ambiguous parse result!"
process :: (ArrowXml a) => a XmlTree ([Sentence String])
process = getChildren >>> listA (tag "sentence" >>> listA word >>> arr (\ns -> Sentence ns))
word :: (ArrowXml a) => a XmlTree (Node String)
word = tag "word" >>> getAttrValue "form" >>> arr (\s -> Word s)
-- | Gets the tag with the given name below the node.
tag :: (ArrowXml a) => String -> a XmlTree XmlTree
tag s = getChildren >>> isElem >>> hasName s
Я пытаюсь прочитать файл корпуса, и структура, очевидно, что-то вроде <corpus><sentence><word form="Hello"/><word form="world"/></sentence></corpus>
,
Даже на очень маленьком корпусе разработки программа зачитывает ~15 секунд, из которых около 20% - время GC (это слишком много).
В частности, много данных тратит слишком много времени в состоянии DRAG. Это профиль:
Мониторинг виновников DRAG. Вы можете видеть, что decodeDocument часто вызывается, и его данные затем останавливаются до самого конца выполнения.
Теперь я думаю, что это должно быть легко исправлено путем добавления всего этого decodeDocument в мои структуры данных (Sentence
а также Word
) и тогда РТ может забыть об этих громах. Однако в настоящее время происходит то, что свертывание происходит в самом конце, когда я форсирую вычисление деконструкцией Either
в IO
Монада, где это может легко произойти в Интернете. Я не вижу причин для этого, и мои попытки ужесточить программу до сих пор были тщетными. Я надеюсь, что кто-нибудь может мне помочь:-)
Я просто не могу понять, слишком много мест, чтобы положить seq
с и $!
в...
1 ответ
Одна возможная вещь, которую можно попробовать: hxt-анализатор по умолчанию является строгим, но существует ленивый синтаксический анализатор, основанный на тегах: http://hackage.haskell.org/package/hxt-tagsoup
В понимании, что экспат может также выполнять ленивую обработку: http://hackage.haskell.org/package/hxt-expat
Возможно, вы захотите узнать, решает ли ваша проблема переключение бэкэндов само по себе.