126

Haskell(主にGHCを使用)にあるデータ型の値を格納するために必要な実際のメモリ量をどのように見つけることができますか?実行時に(たとえばGHCiで)それを評価することは可能ですか、それともそのコンポーネントから複合データ型のメモリ要件を推定することは可能ですか?

a一般に、タイプとのメモリ要件bがわかっている場合、次のような代数的データ型のメモリオーバーヘッドはどのくらいですか。

data Uno = Uno a
data Due = Due a b

たとえば、これらの値はメモリ内で何バイトを占めますか?

1 :: Int8
1 :: Integer
2^100 :: Integer
\x -> x + 1
(1 :: Int8, 2 :: Int8)
[1] :: [Int8]
Just (1 :: Int8)
Nothing

ガベージコレクションが遅れているため、実際のメモリ割り当てが多いことを理解しています。遅延評価のために大幅に異なる場合があります(サンクサイズは値のサイズとは関係ありません)。問題は、データ型が与えられた場合、完全に評価されたときにその値がどのくらいのメモリを消費するかということです。

GHCiにはメモリ統計を表示するオプションがあることがわかりましたが:set +s、単一の値のメモリフットプリントを見積もる方法が明確ではありません。

4

2 に答える 2

158

(以下はGHCに適用され、他のコンパイラーは異なるストレージ規則を使用する場合があります)

経験則:コンストラクターは、ヘッダーに1ワード、各フィールドに1ワードかかります。例外:GHCはこれらのコンストラクターの単一のインスタンスを作成し、それをすべての用途で共有するため、フィールド(Nothingまたはなど)のないコンストラクターはスペースを取りません。True

ワードは、32ビットマシンでは4バイト、64ビットマシンでは8バイトです。

だから例えば

data Uno = Uno a
data Due = Due a b

anUnoは2語、aDueは3語かかります。

タイプは次のIntように定義されます

data Int = I# Int#

今、Int#1つの単語をInt取るので、合計2つかかります。ほとんどのボックス化されていない型は1ワードを取りますが、例外は、、、および(32ビットマシンの場合)2を取ります。GHCInt64#Word64#Double#実際には型Intとの小さな値のキャッシュがCharあるため、多くの場合、これらはヒープスペースをまったく必要としません。s> 255を使用しない限り、 aStringはリストセル用のスペースのみを必要とします。Char

はとInt8同じ表現Intです。 Integerこのように定義されます:

data Integer
  = S# Int#                            -- small integers
  | J# Int# ByteArray#                 -- large integers

したがって、小さいIntegerS#)は2ワードを取りますが、大きい整数はその値に応じて可変量のスペースを取ります。AByteArray#は、2ワード(ヘッダー+サイズ)と配列自体のスペースを取ります。

で定義されたコンストラクターnewtypeは無料であることに注意してください。 newtypeは純粋にコンパイル時のアイデアであり、実行時にスペースや命令を消費しません。

詳細については、GHC解説のヒープオブジェクトのレイアウトを参照してください。

于 2010-07-15T14:56:14.767 に答える
5

ghc-datasizeパッケージは、GHCオブジェクトのサイズを計算するためのrecursiveSize関数を提供します。でも...

ガベージコレクターはヒープウォークを困難にするため、サイズが計算される前にガベージコレクションが実行されます。

...したがって、これを頻繁に呼び出すのは実用的ではありません!

データ型のGHCのメモリ表現を見つける方法も参照してください。Haskellでタイプのサイズを決定するにはどうすればよいですか?

于 2015-09-21T15:00:25.790 に答える