我们可以在Haskell中编写一个函数来测量n个字符的字符串占用的字节数吗?

haw*_*eye 4 byte haskell heap-memory

假设我有字符串

"abc"
Run Code Online (Sandbox Code Playgroud)

我想计算它在内存中占用的字节数。

我可以做:

import Data.Bits
finiteBitSize ("abc" :: [Char])
Run Code Online (Sandbox Code Playgroud)

但这会中断,因为[Char]该功能不支持该类型。(也是位而不是字节,但重点是画一张我要寻找的图片)。

我的问题是:我们可以在Haskell中编写一个函数来测量n个字符的字符串占用的字节数吗?

Dan*_*ner 14

情况很复杂。

让我们谈谈GHC,String尤其是关于GHC的讨论,并假设它已经过全面评估,因此我们没有以GC友好的方式迭代使用它,也没有延迟评估并存储一个小的thunk表示。巨大的数据结构。

在做出所有简化的假设之后,我们将需要了解一些定义。

type String = [Char]
data [a] = [] | a : [a] -- pseudosyntax
data Char = C# Char# -- I'm guessing, couldn't find a canonical source
Run Code Online (Sandbox Code Playgroud)

现在,我们将使用一些经验法则。首先:未装箱的东西(例如Char#)通常存储在一个机器字中。我们生活在一个64位计算机的世界中,因此Char#大约8个字节,即使它可能仅使用了它的最低4个字节。第二:数据构造函数是一个用来说出哪个构造函数的单词,再加上一个指向每个字段的单词。

现在我们准备好了。

空字符串是[],对于构造函数来说是一个单词,对于字段来说没有单词,因此总共一个单词。

非空字符串是c : cs,因此,对于:构造函数来说,是一个字c,要指向的是cs一个字,对于C#构造函数来说,是一个字,对于构造函数来说,一个字是,对于Char#。这是5个字,加上我们需要的许多字cs

因此,对于String长度为n的a,我们有5 * n个词来表示的主体,String而对于终止符则有一个额外的词[]。实际上,每个字符40个字节!kes。

现在,您知道为什么打包表示Text(例如,或在适当时使用ByteString)如此重要。

  • @dfeuer啊,我敢打赌!我敢打赌的原因是,我在另一个问题(现在很难找到)上发现,与我对最大居住人数的观察相比,该答案中的估算值过高。共享小型`Char's也许可以解释这种差异。 (3认同)
  • @dfeuer一些简单的测试似乎支持以下假设:`readFile“ foo” >> = \ s-> print(length s)>> print(length s)如果foo`具有`',则占用的最大驻留时间大约是原来的两倍。 1114111's中的值,如果其中有'a'`s。 (2认同)
  • 是的,ghc会预先分配ASCII字符并确保在GC中共享。它和小的Int技巧都是它从hbc继承的东西。 (2认同)