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
지연된 가비지 수집으로 인해 실제 메모리 할당이 더 높다는 것을 알고 있습니다. 지연 평가로 인해 상당히 다를 수 있습니다 (그리고 썽크 크기는 값의 크기와 관련이 없습니다). 질문은 데이터 유형이 주어지면 그 값이 완전히 평가 될 때 얼마나 많은 메모리를 차지합니까?
:set +s
GHCi에는 메모리 통계를 볼 수 있는 옵션이 있지만 단일 값의 메모리 사용량을 추정하는 방법은 명확하지 않습니다.
답변
(다음은 GHC에 적용되며 다른 컴파일러는 다른 저장소 규칙을 사용할 수 있습니다.)
경험 법칙 : 생성자는 헤더 당 한 단어, 각 필드 당 한 단어의 비용이 듭니다 . 예외 : 필드가없는 생성자 (예 : Nothing
또는 True
)는 공간을 차지하지 않습니다. GHC는 이러한 생성자의 단일 인스턴스를 만들고 모든 용도에서 공유하기 때문입니다.
워드는 32 비트 시스템에서 4 바이트이고 64 비트 시스템에서 8 바이트입니다.
그래서 예
data Uno = Uno a
data Due = Due a b
a Uno
는 2 단어를 취하고 a Due
는 3 단어를 취합니다.
Int
타입으로 정의
data Int = I# Int#
이제 Int#
한 단어를 사용하므로 Int
총 2 개를 사용합니다. 대부분의 언 박싱 된 유형은 예외가되고, 하나의 말을 Int64#
, Word64#
그리고 Double#
2 GHC 실제로 유형의 작은 값의 캐시가 가지고있는 (32 비트 시스템에서) Int
하고 Char
, 많은 경우에 이러한 전혀 힙 공간을 차지하지 않습니다. s> 255 String
를 사용하지 않는 한 A 는 목록 셀을위한 공간 만 필요합니다 Char
.
은 Int8
동일한 표현을 갖는다 Int
. Integer
다음과 같이 정의됩니다.
data Integer
= S# Int# -- small integers
| J# Int# ByteArray# -- large integers
따라서 작은 Integer
( S#
)은 2 단어를 사용하지만 큰 정수는 값에 따라 가변적 인 공간을 차지합니다. A ByteArray#
는 2 개의 단어 (헤더 + 크기)와 배열 자체를위한 공간을 사용합니다.
로 정의 된 생성자 newtype
는 free 입니다. newtype
순전히 컴파일 타임 아이디어이며 공간을 차지하지 않으며 런타임에 지침이 들지 않습니다.
답변
ghc-datasize 패키지는 GHC 객체의 크기를 계산하는 recursiveSize 함수를 제공 합니다. 하나…
가비지 수집기는 힙 이동을 어렵게 만들기 때문에 크기가 계산되기 전에 가비지 수집이 수행됩니다.
… 그래서 이것을 자주 부르는 것은 실용적이지 않을 것입니다!
또한 데이터 유형에 대한 GHC의 메모리 표현을 찾는 방법을 참조하십시오 . 그리고 어떻게 하스켈 타입의 크기를 확인할 수 있습니까? .