Объем памяти типов данных Haskell
как я могу найти фактический объем памяти, необходимый для хранения значения некоторого типа данных в 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
Я понимаю, что фактическое выделение памяти выше из-за задержки сбора мусора. Он может значительно отличаться из-за ленивой оценки (и размер thunk не связан с размером значения). Вопрос в том, учитывая тип данных, сколько памяти занимает его значение при полной оценке?
я обнаружил, что есть :set +s
опция в GHCi для просмотра статистики памяти, но не ясно, как оценить объем памяти a одно значение.
2 ответа:
(следующее относится к GHC, другие компиляторы могут использовать различные соглашения о хранении)
правило: конструктор стоит одно слово для заголовка, и одно слово для каждого поля. Исключение: конструктор без полей (например,
Nothing
илиTrue
) не занимает места, потому что GHC создает один экземпляр этих конструкторов и разделяет его среди всех применений.слово составляет 4 байта на 32-разрядной машине и 8 байт на 64-разрядной машина.
так, например,
data Uno = Uno a data Due = Due a b
an
Uno
принимает 2 слова, иDue
занимает 3.The
Int
тип определяется какdata Int = I# Int#
теперь
Int#
берет одно слово, такInt
занимает 2 в общей сложности. Большинство распакованных типов принимают одно слово, исключение составляетInt64#
,Word64#
иDouble#
(на 32-разрядной машине), которые принимают 2. GHC на самом деле имеет кэш небольших значений типаInt
иChar
, так что во многих случаях они не принимают кучу космос вообще. АString
требуется только место для ячеек списка, если вы не используетеChar
s > 255.An
Int8
имеет идентичное представлениеInt
.Integer
определяется следующим образом:data Integer = S# Int# -- small integers | J# Int# ByteArray# -- large integers
так маленький
Integer
(S#
) занимает 2 слова, но большое целое число занимает разное количество места в зависимости от его стоимости. АByteArray#
занимает 2 слова (заголовок + размер) плюс пространство для самого массива.отметим, что определен конструктор с
newtype
свободный.newtype
это чисто идея времени компиляции, и она не занимает места и не стоит никаких инструкций во время выполнения.Подробнее расположение объектов кучи в комментарии GHC.
пакет ghc-datasize предоставляет recursiveSize функция для вычисления размера объекта GHC. Однако...
сбор мусора выполняется перед вычислением размера, потому что сборщик мусора сделает кучи прогулки трудно.
... так что было бы нецелесообразно называть это часто!
см. Также как узнать представления памяти GHC типов данных? и как я могу определите размер типа в Haskell?.