可不可以在Haskell中写一个函数,统计n个字符的字符串占用的字节数?
Can we write a function in Haskell to measure the number of bytes that a string of n characters occupies?
假设我有字符串
"abc"
并且我想计算它在内存中占用的字节数。
我能做到:
import Data.Bits
finiteBitSize ("abc" :: [Char])
但这会中断,因为 [Char]
不是该函数支持的类型。 (它也是位而不是字节,但重点是描绘我正在寻找的图片)。
我的问题是:我们可以在Haskell中写一个函数来测量一个n个字符的字符串占用的字节数吗?
这很复杂。
让我们谈谈 GHC,具体来说 String
,假设这件事已经过全面评估,所以我们没有以 GC 友好的方式迭代使用它,我们也没有开始延迟评估并存储一个代表巨大数据结构的微小 thunk。
在做出所有这些简化假设之后,我们需要了解一些定义。
type String = [Char]
data [a] = [] | a : [a] -- pseudosyntax
data Char = C# Char# -- I'm guessing, couldn't find a canonical source
现在我们将使用一些经验法则。第一:未装箱的东西(如Char#
)通常存储在机器字中。我们生活在一个 64 位机器的世界中,所以 Char#
可能是 8 个字节,即使它可能只使用它的底部 4 个字节。第二:data constructors是一个word表示是哪个constructor,再加一个word指向各个字段。
现在我们准备好了。
空字符串是[]
,构造函数一个词,字段没有词,所以总共一个词。
非空字符串是c : cs
,所以:
构造函数一个词,一个词指向c
,一个词指向cs
,一个词对于 C#
构造函数,一个词对于 Char#
。这是 5 个单词加上我们 cs
.
需要的单词
所以对于长度为 n 的 String
,我们有 5*n 个词来表示 String
的正文,还有一个额外的词用于终止 []
。实际上每个字符 40 个字节!哎呀。
现在您知道为什么像 Text
(或者,在适当的时候,ByteString
)这样的打包表示如此重要。
有一个名为 ghc-datasize
的 Haskell 程序包,它允许您计算每个 Haskell 值 实际 占用的内存。您甚至可以在官方 Hackage 文档中看到如何计算字符串大小的示例:
要计算 String
的长度,您需要使用以下函数:
recursiveSize :: a -> IO Word
看起来像这样:
ghci> recursiveSize $!! "foobar"
240
假设我有字符串
"abc"
并且我想计算它在内存中占用的字节数。
我能做到:
import Data.Bits
finiteBitSize ("abc" :: [Char])
但这会中断,因为 [Char]
不是该函数支持的类型。 (它也是位而不是字节,但重点是描绘我正在寻找的图片)。
我的问题是:我们可以在Haskell中写一个函数来测量一个n个字符的字符串占用的字节数吗?
这很复杂。
让我们谈谈 GHC,具体来说 String
,假设这件事已经过全面评估,所以我们没有以 GC 友好的方式迭代使用它,我们也没有开始延迟评估并存储一个代表巨大数据结构的微小 thunk。
在做出所有这些简化假设之后,我们需要了解一些定义。
type String = [Char]
data [a] = [] | a : [a] -- pseudosyntax
data Char = C# Char# -- I'm guessing, couldn't find a canonical source
现在我们将使用一些经验法则。第一:未装箱的东西(如Char#
)通常存储在机器字中。我们生活在一个 64 位机器的世界中,所以 Char#
可能是 8 个字节,即使它可能只使用它的底部 4 个字节。第二:data constructors是一个word表示是哪个constructor,再加一个word指向各个字段。
现在我们准备好了。
空字符串是[]
,构造函数一个词,字段没有词,所以总共一个词。
非空字符串是c : cs
,所以:
构造函数一个词,一个词指向c
,一个词指向cs
,一个词对于 C#
构造函数,一个词对于 Char#
。这是 5 个单词加上我们 cs
.
所以对于长度为 n 的 String
,我们有 5*n 个词来表示 String
的正文,还有一个额外的词用于终止 []
。实际上每个字符 40 个字节!哎呀。
现在您知道为什么像 Text
(或者,在适当的时候,ByteString
)这样的打包表示如此重要。
有一个名为 ghc-datasize
的 Haskell 程序包,它允许您计算每个 Haskell 值 实际 占用的内存。您甚至可以在官方 Hackage 文档中看到如何计算字符串大小的示例:
要计算 String
的长度,您需要使用以下函数:
recursiveSize :: a -> IO Word
看起来像这样:
ghci> recursiveSize $!! "foobar"
240