2016-08-03 8 views
4

Я пытаюсь создать профиль памяти кучи для следующих наивной коды Haskell, который копирует файл:Нет кучи данных профилирования для модуля Data.ByteString

import System.Environment 
import System.IO 
import qualified Data.ByteString as B 
import qualified Data.ByteString.Lazy as LB 

naiveCopy :: String -> String -> IO() 
naiveCopy from to = do 
    putStrLn $ "From: " ++ from 
    putStrLn $ "To: " ++ to 
    s <- B.readFile from 
    B.writeFile to s 

main = do 
    args <- getArgs 
    mapM (\ x-> putStrLn x) args 
    naiveCopy (head args) ((head.tail) args) 

команды, которые строят код с GHC 8.0.1:

ghc -o t -rtsopts -prof -fprof-auto t.hs 

Команда, которая собирает данные профилирования:

./t +RTS -p -h -RTS in/data out/data && hp2ps -e8in -c t.hp 

in/data где является довольно большой файл (около 500 МБ), который займет около 2 секунд для копирования.

Проблема заключается в том, что я не мог GET кучного профилирование данных, если я использую строгий Data.ByteString, есть только небольшой t.hp файл без каких-либо образцов данных, это выглядит следующим образом:

JOB "t in/data out/data +RTS -p -h" 
DATE "Thu Aug 4 20:19 2016" 
SAMPLE_UNIT "seconds" 
VALUE_UNIT "bytes" 
BEGIN_SAMPLE 0.000000 
END_SAMPLE 0.000000 
BEGIN_SAMPLE 0.943188 
END_SAMPLE 0.943188 

и соответствующий профиль диаграмма, как это: Strict ByteString without profiling data

Однако я мог получить данные кучи профилирования при переходе на ленивую версию Data.ByteString.Lazy, профиль диаграмма, как это: Lazy ByteString with profiling data

Обновление: Спасибо @ryachza, я добавил параметр -i0 установить интервал выборки и попробовал еще раз, на этот раз я получил образец данных для строгого ByteString, и это выглядело разумным (я копировал 500M файл и пик выделения памяти в следующем профилировании графика составляет около 500M)

./t +RTS -p -h -RTS in/data out/data && hp2ps -e8in -c t.hp 

Strict ByteString with profiling data

+2

Просьба пояснить, «не удалось получить данные профилирования кучи». Что пошло не так? –

+0

Проблема заключается в том, что в файле * * .hp нет образца профиля, все, что я получил, было похоже на простой заголовок файла: JOB «t in/data out/data + RTS -p -h» ДАТА «Thu 4 августа 20:19 +2016" SAMPLE_UNIT "секунды" VALUE_UNIT "байты" BEGIN_SAMPLE 0,000000 END_SAMPLE 0,000000 BEGIN_SAMPLE 0,943188 0,943188 END_SAMPLE – 6bb79df9

ответ

4

оказывается, как ты gh время выполнения не «получает шанс измерить» кучу. Если вы добавите -s в свои RTS, он должен распечатать некоторое время и информацию о размещении. Когда я запускаю это, я вижу, что выделенные байты и общее использование памяти очень велики (размер файла), но максимальная резидентность (и количество выборок) очень низкая, а в то время как прошедшее время является высоким, фактическая «работа "время практически 0.

Добавление опции RTS -i0 позволило мне воспроизводимо визуализировать распределение байтовой строки в PINNED (это классификация, так как массивы байтов, которые байтовой строки использует внутренне распределены в области, в которой GC не может перемещать вещи). Вы можете поэкспериментировать с различными параметрами -h, которые связывают распределения с различными центрами затрат (например, -hy должен показывать ARR_WORDS), но, вероятно, это не будет иметь большого значения в этом случае, так как байты являются действительно «большими кусками необработанной памяти».

Ссылки я использовал, чтобы найти RTS варианты были (очевидно, я не был особенно о версии GHC - я не могу себе представить, эти флаги часто меняются):

  1. https://downloads.haskell.org/~ghc/7.0.1/docs/html/users_guide/runtime-control.html
  2. https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/profiling.html