所以我有一个位置类。
我该如何让
对于更具攻击性的
如果我使用一个非常基本的惰性构建器,没有重复的破折号。
data Location = Location {
title :: String
, description :: String
}
instance Show Location where
show l = title l ++ "\n"
++ replicate (length $ title l) '-' ++ "\n"
++ description l
接着我改用了Data.Text
data Location = Location {
title :: Text
, description :: Text
}
instance Show Location where
show l = T.unpack $
title l <> "\n"
<> T.replicate (T.length $ title l) "-" <> "\n"
<> description l
使用 Criterion,我对 String
和 Data.Text
实现的 show
函数所需时间进行了基准测试:
benchmarks = [ bench "show" (whnf show l) ]
where l = Location {
title="My Title"
, description = "This is the description."
}
String
的实现只需要34纳秒,而Data.Text
的实现要慢近六倍,需要170纳秒。我该如何让
Data.Text
的速度与String
一样快呢?
编辑:愚蠢的错误
我不确定怎么会出现这种情况,但我无法复制最初的速度差异:现在对于String和Text,我分别得到28ns和24ns。对于更具攻击性的
bench "length.show" (whnf (length . show) l)
基准测试,对于String和Text,我分别得到467ns和3954ns。如果我使用一个非常基本的惰性构建器,没有重复的破折号。
import qualified Data.Text.Lazy.Builder as Bldr
instance Show Location where
show l = show $
Bldr.fromText (title l) <> Bldr.singleton '\n'
-- <> Bldr.fromText (T.replicate (T.length $ title l) "-") <> Bldr.singleton '\n'
<> Bldr.fromText (description l)
当我尝试使用原始的普通show
基准测试时,得到了19ns。现在这有点错误,因为使用show
将构建器转换为字符串会转义换行符。如果我将其替换为LT.unpack $ Bldr.toLazyText
,其中LT
是Data.Text.Lazy
的限定导入,则我会得到192ns。
我在Mac笔记本电脑上进行测试,我怀疑我的时间测量结果可能会受到机器噪声的干扰。感谢您的指导。