模块Data.ByteString没有堆分析数据

时间:2016-08-03 14:06:36

标签: haskell bytestring memory-profiling

我正在尝试生成堆内存配置文件,以便跟踪复制文件的朴素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是一个非常大的文件(大约500MB),这将花费大约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

和相应的个人资料图表如下: 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

1 个答案:

答案 0 :(得分:4)

似乎运行时没有“有机会测量”堆。如果您将-s添加到RTS选项,则应打印一些时间和分配信息。当我运行它时,我看到分配的字节数和总内存使用量非常高(文件的大小),但是最大驻留时间(和样本数)非常低,而且经过的时间很长,实际的“工作” “时间几乎为零。

添加RTS选项-i0允许我可重复地将字节串分配可视化为PINNED(这是分类,因为bytestring内部使用的字节数组分配在GC可以的区域中' t搬东西)。您可以尝试使用不同的-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