Объем памяти типов данных 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 ban
Unoпринимает 2 слова, иDueзанимает 3.The
Intтип определяется какdata Int = I# Int#теперь
Int#берет одно слово, такIntзанимает 2 в общей сложности. Большинство распакованных типов принимают одно слово, исключение составляетInt64#,Word64#иDouble#(на 32-разрядной машине), которые принимают 2. GHC на самом деле имеет кэш небольших значений типаIntиChar, так что во многих случаях они не принимают кучу космос вообще. АStringтребуется только место для ячеек списка, если вы не используетеChars > 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?.