metaclass: (Default)
metaclass ([personal profile] metaclass) wrote2011-10-31 04:45 pm
Entry tags:

Haskell, профилировщик

Проверяю, действительно ли enumerator+attoparsec работают в постоянной памяти.
Собираю с профилировочной информацией:
ghc.exe -odir obj -hidir obj --make "%1" -prof -auto-all -caf-all -fforce-recomp -rtsopts -fext-core
(если чо - в кабале перед установкой пакетов надо в конфиг поставить опцию library-profiling: True иначе будет ругаться при сборке)

затем запускаю прожку с профилировщиком
test.exe +RTS -p list2.txt >rr

list2.txt - файлик в 18 мег, 316 тыщ строк, список файлов на диске С :)

получаю файл test.prof, в котором есть такая забавная информация:
COST CENTRE                    MODULE               %time %alloc
main                           Main                  48.6    8.7
notNewLine                     Parsers               36.0   73.4
parseLine                      Parsers               10.6   15.5


notNewLine, который так интенсивно долбится в память - совершенно тупой предикат:
notNewLine :: Word8 -> Bool
notNewLine 10 = False -- LF
notNewLine 13 = False -- CR
notNewLine _  = True


Решил глянуть, что же ghc генерит для него:

  main:Parsers.notNewLine :: base:GHCziWord.Word8 ->
                             ghczmprim:GHCziBool.Bool =
    \ (dsd2xh::base:GHCziWord.Word8) ->
        %note "SCC"
        %case ghczmprim:GHCziBool.Bool (base:GHCziClasses.zeze
                                        @ base:GHCziWord.Word8 base:GHCziWord.zdfEqWord8 dsd2xh
                                        (base:GHCziNum.fromInteger @ base:GHCziWord.Word8
                                         base:GHCziWord.zdfNumWord8
                                         (integerzmgmp:GHCziInteger.smallInteger
                                          (10::ghczmprim:GHCziPrim.Intzh))))
        %of (wildB1::ghczmprim:GHCziBool.Bool)
          {ghczmprim:GHCziBool.False ->
             %case ghczmprim:GHCziBool.Bool (base:GHCziClasses.zeze
                                             @ base:GHCziWord.Word8 base:GHCziWord.zdfEqWord8 dsd2xh
                                             (base:GHCziNum.fromInteger @ base:GHCziWord.Word8
                                              base:GHCziWord.zdfNumWord8
                                              (integerzmgmp:GHCziInteger.smallInteger
                                               (13::ghczmprim:GHCziPrim.Intzh))))
             %of (wild1X9::ghczmprim:GHCziBool.Bool)
               {ghczmprim:GHCziBool.False ->
                  ghczmprim:GHCziBool.True;
                ghczmprim:GHCziBool.True ->
                  ghczmprim:GHCziBool.False};
           ghczmprim:GHCziBool.True ->
             ghczmprim:GHCziBool.False};



Если я правильно понимаю написанное - оно на каждый вызов предиката конвертирует числа в Word8, выделяя под это память, а то и не один раз?
Хотя это какая-то хрень, оно должно такое вычислить один раз и дальше использовать готовое, по идее.

PS: Ага, включил -O2 - предикат стал работать как положено - 2% времени и 0% памяти. И общее потребление памяти вообще упало в 5 раз.

[identity profile] geeks-ru.livejournal.com 2011-10-31 03:46 pm (UTC)(link)
А оптимизация там проводится? (не вижу флага -O, он совместим с профилированием?)

[identity profile] nealar.livejournal.com 2011-11-01 04:42 am (UTC)(link)
Несовместим. -O2 часто отрезает то, что проставил -auto-all.