Нет данных профилирования кучи для модуля Data.ByteString

Я пытался сгенерировать профиль памяти кучи для следующего наивного кода на Haskell, который копирует файл:

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 секунд.

Проблема в том, что я не могу получить данные профилирования кучи, если я использую строгий 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

и соответствующий профиль профиля, как это: Строгая ByteString без данных профилирования

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

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

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

Строгая ByteString с данными профилирования

1 ответ

Решение

Похоже, что среда выполнения не "получает возможность измерить" кучу. Если вы добавите -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
Другие вопросы по тегам