Édité pour corriger certains détails re: quads étant 8 octets et expliquant le champ lien statique.
Je pense unsafeSizeOf
est inexacte et vous interprétez mal sa sortie. Notez qu'il est destiné à montrer l'utilisation de la mémoire pour la fermeture de niveau supérieur seulement, pas l'utilisation totale de l'espace de l'objet. Qu'est-ce que vous voyez, je pense, est que q
nécessite 10 octets plus au tuple p
(alors que p
nécessite 10 octets plus au Int
boxed Char
et mis en boîte). De plus, mes tests indiquent que les constructeurs de niveau supérieur ont besoin de 24 octets chacun (sur une architecture 64 bits), même si unsafeSizeOf
rapporte 10 pour moi aussi.
si je compile, en particulier, le programme de test suivant avec stack ghc -- -fforce-recomp -ddump-asm -dsuppress-all -O2 ZeroMemory.hs
en utilisant GHC 8.0.2:
{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeFamilies #-}
module ZeroMemory where
data Uncurry (a :: i -> j -> *) (z :: (i, j)) =
forall x y . z ~ '(x,y) => Uncurry !(a x y)
q :: Uncurry (,) '(Int, Char)
q = Uncurry (0, '\0')
r :: Uncurry (,) '(Int, Char)
r = Uncurry (1, '\1')
puis la fermeture empreinte mémoire pour le haut niveau q
ressemble:
q_closure:
.quad Uncurry_static_info
.quad $s$WUncurry_$d~~_closure+1
.quad q1_closure+1
.quad 3
Notez que chaque .quad
est actuellement 8 octets; c'est un "quad" de "mots" 16 bits à l'ancienne. Je crois que le dernier quad
ici, avec la valeur 3, est le "champ de lien statique" décrit dans the GHC implementation commentary et ne s'applique donc pas aux objets d'allocation de tas "typiques".
Ainsi, en ignorant ce dernier champ, la taille totale du niveau supérieur de fermeture q
est de 24 octets, et il se réfère à la q1_closure
qui représente le tuple contenait:
q1_closure:
.quad (,)_static_info
.quad q3_closure+1
.quad q2_closure+1
.quad 3
pendant 24 octets.
q2
Les
et q3
fermetures sont les encadrés Int
et Char
et ainsi prendre deux quartes (16 octets) chacune. Donc, q
prend un total de 10 quads, ou 80 octets. (J'ai inclus r
comme vérification de santé mentale pour m'assurer que je n'identifiais pas les informations partagées.
Un tuple de p
aurait à lui seul une empreinte mémoire équivalente à q1_closure
, soit 7 quads ou 56 octets.
Ce serait très bien d'avoir cette optimisation. Voir https://ghc.haskell.org/trac/ghc/wiki/NewtypeOptimizationForGADTS. Malheureusement, les experts n'ont pas encore compris comment faire pour que tout fonctionne correctement. – dfeuer