了解 Haskell 分析报告中的成本中心名称
Understanding cost center names in Haskell profiling reports
我正在尝试解码 Haskell 分析输出中各种成本中心名称的含义。这是 .prof
文件
的示例
COST CENTRE MODULE no. entries %time %alloc %time %alloc
...
runSiT.\.\.readBufResults SiT.SiT 3487 0 0.0 46.3 51.9
...
...
readBuffer.(...) SiT.SiT 3540 1 0.0 0.2 0.0 0.2
readBuffer.tm0_vals SiT.SiT 3539 1 0.0 0.0 0.0 0.0
readBuffer.\ SiT.SiT 3499 0 18.4 12.8 31.0 27.7
...
似乎一个点分隔了嵌套的成本中心(例如 readBuffer.n_threads
表示 readBuffer
中的绑定 n_threads
),但我不确定其他一些元素。 .\.\.
表示嵌套的 lambda 函数(例如来自 forM_ ... $ \arg -> do
之类的东西)。 但是readBuffer.(...)
中的(...)
是什么意思呢?
编辑:
作为第二个例子,我有:
statsFields.mkStr.\ Main 3801 4 0.0 0.0 0.0 0.0
statsFields.fmtModePct Main 3811 2 0.0 0.0 0.0 0.0
statsFields.fmtModePct.pct_str Main 3815 2 0.0 0.0 0.0 0.0
ssN SiT.SiT 3817 2 0.0 0.0 0.0 0.0
statsFields.fmtPctI Main 3816 2 0.0 0.0 0.0 0.0
statsFields.fmtModePct.(...) Main 3813 2 0.0 0.0 0.0 0.0
ssMode SiT.SiT 3814 2 0.0 0.0 0.0 0.0
statsFields.fmtModePct.m_fq Main 3812 2 0.0 0.0 0.0 0.0
来源是:
where ...
fmtModePct :: SiTStats -> String
fmtModePct ss = fmtI64 m_fq ++ " (" ++ pct_str ++ ")"
where (m_val,m_fq) = ssMode ss
pct_str = fmtPctI m_fq (ssN ss)
fmtF64 :: Double -> String
fmtF64 = commafy . printf "%.1f"
-- turns 1000 -> 1,000
commafy :: String -> String
commafy str
| head str == '-' = '-':commafy (tail str)
| otherwise = reverse (go (reverse sig)) ++ frac
where (sig,frac) = span (/='.') str
go (a:b:c:cs@(_:_)) = a : b : c : ',' : go cs
go str = str
(...) 表示可重复操作,类似于递归调用。在调查我的程序时,我有同样的问题。看下面这个简单的例子,我正在递归地计算 count
和 mergeAndCount
:
count :: [Int] -> (Int, [Int])
count [] = (0, [])
count (x:[]) = (0, [x])
count xs =
let halves = splitAt (length xs `div` 2) xs
(ac, a) = count $ fst halves
(bc, b) = count $ snd halves
(mc, merged) = mergeAndCount a b
in
(ac + bc + mc, merged)
mergeAndCount :: [Int] -> [Int] -> (Int, [Int])
mergeAndCount [] [] = (0, [])
mergeAndCount xs [] = (0, xs)
mergeAndCount [] ys = (0, ys)
mergeAndCount xs@(x:xs') ys@(y:ys') =
let (larger, thisCount, (counted, merged))
= if x < y
then (x, 0, mergeAndCount xs' ys)
else (y, length xs, mergeAndCount xs ys')
in
(thisCount + counted, larger : merged)
将生成类似于
的分析输出
count Invariant 103 199999 0.1 4.3 99.2 37.5
count.merged Invariant 118 99998 0.0 0.0 0.0 0.0
count.a Invariant 113 99999 0.0 0.0 0.0 0.0
count.b Invariant 112 99999 0.0 0.0 0.0 0.0
count.(...) Invariant 110 99999 0.0 0.0 99.0 25.2
mergeAndCount Invariant 111 1636301 98.9 25.2 99.0 25.2
mergeAndCount.merged Invariant 122 726644 0.0 0.0 0.0 0.0
mergeAndCount.merged Invariant 121 709659 0.0 0.0 0.0 0.0
mergeAndCount.(...) Invariant 120 776644 0.0 0.0 0.0 0.0
mergeAndCount.cnt Invariant 119 776644 0.0 0.0 0.0 0.0
mergeAndCount.(...) Invariant 117 759658 0.0 0.0 0.0 0.0
mergeAndCount.cnt Invariant 116 759658 0.0 0.0 0.0
其中 count.merged
表示总体结果,count.a
count.b
函数模式匹配的成本中心。这个 (...)
在每次内部调用 mergeAndCount
时都清晰可见。
如果您的函数包含许多不同的数据处理方法,您的分析输出将不同并且与您发送的数据高度相关。
我正在尝试解码 Haskell 分析输出中各种成本中心名称的含义。这是 .prof
文件
COST CENTRE MODULE no. entries %time %alloc %time %alloc
...
runSiT.\.\.readBufResults SiT.SiT 3487 0 0.0 46.3 51.9
...
...
readBuffer.(...) SiT.SiT 3540 1 0.0 0.2 0.0 0.2
readBuffer.tm0_vals SiT.SiT 3539 1 0.0 0.0 0.0 0.0
readBuffer.\ SiT.SiT 3499 0 18.4 12.8 31.0 27.7
...
似乎一个点分隔了嵌套的成本中心(例如 readBuffer.n_threads
表示 readBuffer
中的绑定 n_threads
),但我不确定其他一些元素。 .\.\.
表示嵌套的 lambda 函数(例如来自 forM_ ... $ \arg -> do
之类的东西)。 但是readBuffer.(...)
中的(...)
是什么意思呢?
编辑: 作为第二个例子,我有:
statsFields.mkStr.\ Main 3801 4 0.0 0.0 0.0 0.0
statsFields.fmtModePct Main 3811 2 0.0 0.0 0.0 0.0
statsFields.fmtModePct.pct_str Main 3815 2 0.0 0.0 0.0 0.0
ssN SiT.SiT 3817 2 0.0 0.0 0.0 0.0
statsFields.fmtPctI Main 3816 2 0.0 0.0 0.0 0.0
statsFields.fmtModePct.(...) Main 3813 2 0.0 0.0 0.0 0.0
ssMode SiT.SiT 3814 2 0.0 0.0 0.0 0.0
statsFields.fmtModePct.m_fq Main 3812 2 0.0 0.0 0.0 0.0
来源是:
where ...
fmtModePct :: SiTStats -> String
fmtModePct ss = fmtI64 m_fq ++ " (" ++ pct_str ++ ")"
where (m_val,m_fq) = ssMode ss
pct_str = fmtPctI m_fq (ssN ss)
fmtF64 :: Double -> String
fmtF64 = commafy . printf "%.1f"
-- turns 1000 -> 1,000
commafy :: String -> String
commafy str
| head str == '-' = '-':commafy (tail str)
| otherwise = reverse (go (reverse sig)) ++ frac
where (sig,frac) = span (/='.') str
go (a:b:c:cs@(_:_)) = a : b : c : ',' : go cs
go str = str
(...) 表示可重复操作,类似于递归调用。在调查我的程序时,我有同样的问题。看下面这个简单的例子,我正在递归地计算 count
和 mergeAndCount
:
count :: [Int] -> (Int, [Int])
count [] = (0, [])
count (x:[]) = (0, [x])
count xs =
let halves = splitAt (length xs `div` 2) xs
(ac, a) = count $ fst halves
(bc, b) = count $ snd halves
(mc, merged) = mergeAndCount a b
in
(ac + bc + mc, merged)
mergeAndCount :: [Int] -> [Int] -> (Int, [Int])
mergeAndCount [] [] = (0, [])
mergeAndCount xs [] = (0, xs)
mergeAndCount [] ys = (0, ys)
mergeAndCount xs@(x:xs') ys@(y:ys') =
let (larger, thisCount, (counted, merged))
= if x < y
then (x, 0, mergeAndCount xs' ys)
else (y, length xs, mergeAndCount xs ys')
in
(thisCount + counted, larger : merged)
将生成类似于
的分析输出 count Invariant 103 199999 0.1 4.3 99.2 37.5
count.merged Invariant 118 99998 0.0 0.0 0.0 0.0
count.a Invariant 113 99999 0.0 0.0 0.0 0.0
count.b Invariant 112 99999 0.0 0.0 0.0 0.0
count.(...) Invariant 110 99999 0.0 0.0 99.0 25.2
mergeAndCount Invariant 111 1636301 98.9 25.2 99.0 25.2
mergeAndCount.merged Invariant 122 726644 0.0 0.0 0.0 0.0
mergeAndCount.merged Invariant 121 709659 0.0 0.0 0.0 0.0
mergeAndCount.(...) Invariant 120 776644 0.0 0.0 0.0 0.0
mergeAndCount.cnt Invariant 119 776644 0.0 0.0 0.0 0.0
mergeAndCount.(...) Invariant 117 759658 0.0 0.0 0.0 0.0
mergeAndCount.cnt Invariant 116 759658 0.0 0.0 0.0
其中 count.merged
表示总体结果,count.a
count.b
函数模式匹配的成本中心。这个 (...)
在每次内部调用 mergeAndCount
时都清晰可见。
如果您的函数包含许多不同的数据处理方法,您的分析输出将不同并且与您发送的数据高度相关。