没有模块 Data.ByteString 的堆分析数据
No heap profiling data for module 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
是一个相当大的文件(大约 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
和相应的配置文件图表如下:
然而,如果我切换到惰性版本Data.ByteString.Lazy
,我可以获得堆分析数据,分析图表如下:
更新:谢谢@ryachza,我添加了一个-i0
参数来设置采样间隔并再次尝试,这次我得到了严格ByteString
的样本数据,看起来很合理(我正在复制一个 500M 的文件,下面的分析图表中的内存分配峰值约为 500M)
./t +RTS -p -h -RTS in/data out/data && hp2ps -e8in -c t.hp
似乎 运行 时间不是 "getting the chance to measure" 堆。如果将 -s
添加到 RTS
选项,它应该会打印一些时间和分配信息。当我 运行 这样做时,我看到分配的字节数和总内存使用量非常高(文件大小),但最大驻留时间(和样本数)非常低,而经过的时间却很高实际 "work" 时间实际上是 0.
添加 RTS 选项 -i0
允许我将字节串分配可视化为 PINNED
(这是分类,因为字节串在内部使用的字节数组分配在 GC 所在的区域不能移动东西)。您可以尝试不同的 -h
选项,将分配关联到不同的成本中心(例如,-hy
应该显示 ARR_WORDS
),但在这种情况下它可能没有太大价值,因为字节串真的只是 "big chunks of raw memory".
我用来查找 RTS 选项的参考资料是(显然我对 GHC 版本并不特别——我无法想象这些标志会经常更改):
我正在尝试为以下复制文件的天真 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
和相应的配置文件图表如下:
然而,如果我切换到惰性版本Data.ByteString.Lazy
,我可以获得堆分析数据,分析图表如下:
更新:谢谢@ryachza,我添加了一个-i0
参数来设置采样间隔并再次尝试,这次我得到了严格ByteString
的样本数据,看起来很合理(我正在复制一个 500M 的文件,下面的分析图表中的内存分配峰值约为 500M)
./t +RTS -p -h -RTS in/data out/data && hp2ps -e8in -c t.hp
似乎 运行 时间不是 "getting the chance to measure" 堆。如果将 -s
添加到 RTS
选项,它应该会打印一些时间和分配信息。当我 运行 这样做时,我看到分配的字节数和总内存使用量非常高(文件大小),但最大驻留时间(和样本数)非常低,而经过的时间却很高实际 "work" 时间实际上是 0.
添加 RTS 选项 -i0
允许我将字节串分配可视化为 PINNED
(这是分类,因为字节串在内部使用的字节数组分配在 GC 所在的区域不能移动东西)。您可以尝试不同的 -h
选项,将分配关联到不同的成本中心(例如,-hy
应该显示 ARR_WORDS
),但在这种情况下它可能没有太大价值,因为字节串真的只是 "big chunks of raw memory".
我用来查找 RTS 选项的参考资料是(显然我对 GHC 版本并不特别——我无法想象这些标志会经常更改):