2017-09-19 6 views
5

एक भी सख्त क्षेत्र के साथ एक अस्तित्व डेटा प्रकार तो मेरे पास है:एक भी सख्त क्षेत्र के साथ अस्तित्व डेटा प्रकार

data Uncurry (a :: i -> j -> *) (z :: (i,j)) = 
    forall x y. z ~ '(x,y) => Uncurry !(a x y) 

प्रयोग unsafeSizeof का उपयोग कर (this answer से चोरी) मेरे विश्वास है कि यह शून्य स्मृति हो सकता है भूमि के ऊपर:

λ p = (0, '\0') :: (Int, Char) 
λ q = Uncurry p 
λ unsafeSizeof p 
10 
λ unsafeSizeof q 
10 

तो यह Uncurry की तरह लगता है एक प्रकार की newtype की तरह काम कर रहा है, केवल संकलन समय पर इस्तेमाल किया जा रहा।

यह मुझे समझ में आता है, क्योंकि समानता के दावे के लिए एक शब्दकोश की आवश्यकता नहीं होती है।

क्या यह एक वैध व्याख्या है? क्या मुझे जीएचसी (या हास्केल रिपोर्ट) से इसकी कोई गारंटी है, या क्या मैंने भाग्य से बाहर किया?

+2

यह अनुकूलन होना बहुत अच्छा होगा। Https://ghc.haskell.org/trac/ghc/wiki/NewtypeOptimizationForGADTS देखें। दुर्भाग्य से, विशेषज्ञों ने यह नहीं पता लगाया है कि सबकुछ अभी तक कैसे काम कर रहा है। – dfeuer

उत्तर

6

data कभी भी newtype में परिवर्तित नहीं हुआ है। Uncurry एक नया बंद जोड़ता है, और ~ शब्दकोश के लिए पॉइंटर वास्तव में जीएचसी 8.0.2 के रूप में भी घूमता है। इसलिए, Uncurry में तीन शब्दों के साथ बंद है।

unsafeSizeof, वह सही नहीं है के बाद से शब्दों में इसका आकार Array# स्टोर, जबकि ByteArray# भंडार बाइट में इसके आकार, इसलिए sizeofByteArray# (unsafeCoerce# ptrs) बजाय बाइट्स की इरादा संख्या शब्दों की संख्या देता है। एक सही संस्करण 64 बिट सिस्टम पर इस प्रकार दिखाई देगा:

unsafeSizeof :: a -> Int 
unsafeSizeof !a = 
    case unpackClosure# a of 
    (# x, ptrs, nptrs #) -> 
     I# (8# +# sizeofArray# prts *# 8# +# sizeofByteArray# nptrs) 

लेकिन ध्यान दें कि unsafeSizeof केवल हमें सर्वोच्च बंद के आकार देता है। इसलिए, किसी भी बॉक्स किए गए ट्यूपल का बंद आकार 24 होगा, जो Uncurry t के बंद आकार के साथ मेल खाता है, क्योंकि Uncurry में एक जानकारी सूचक, ~ के लिए एक बेकार सूचक, और ट्यूपल फ़ील्ड के लिए एक सूचक है। यह संयोग पिछली छोटी गाड़ी unsafeSizeof कार्यान्वयन के साथ भी है। लेकिन Uncurry t का कुल आकार t से अधिक है।

5

कुछ विवरण ठीक करने के लिए संपादित किया गया: quads 8 बाइट्स और स्थिर लिंक फ़ील्ड समझाते हैं।

मुझे लगता है कि unsafeSizeOf गलत है और आप इसके आउटपुट को गलत व्याख्या कर रहे हैं। ध्यान दें कि यह केवल शीर्ष-स्तर के बंद होने के लिए स्मृति उपयोग दिखाने का इरादा है, न कि ऑब्जेक्ट का कुल स्थान उपयोग। आप क्या देख रहे हैं, मुझे लगता है, (जबकि pअलावा बॉक्सिंग Char और बॉक्सिंग Int करने के लिए 10 बाइट्स की आवश्यकता है) कि qअलावा टपल p करने के लिए 10 बाइट्स की आवश्यकता है। इसके अलावा, मेरे परीक्षणों से संकेत मिलता है कि शीर्ष-स्तरीय रचनाकारों को वास्तव में 24 बिट्स (64-बिट आर्किटेक्चर पर) की आवश्यकता होती है, भले ही unsafeSizeOf मेरे लिए 10 रिपोर्ट भी करे।

विशेष रूप से, अगर मैं stack ghc -- -fforce-recomp -ddump-asm -dsuppress-all -O2 ZeroMemory.hs 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') 

तो शीर्ष स्तर के लिए स्मृति पदचिह्न q बंद लगता है:

q_closure: 
    .quad Uncurry_static_info 
    .quad $s$WUncurry_$d~~_closure+1 
    .quad q1_closure+1 
    .quad 3 

ध्यान दें कि प्रत्येक .quad वास्तव में 8 बाइट्स है; यह पुरानी शैली के 16-बिट "शब्द" का "क्वाड" है। मेरा मानना ​​है कि अंतिम quad, मूल्य 3 के साथ, the GHC implementation commentary में वर्णित "स्थैतिक लिंक फ़ील्ड" है और इसलिए "सामान्य" ढेर आवंटन ऑब्जेक्ट्स पर लागू नहीं होता है।

तो, यह अंतिम क्षेत्र की अनदेखी कर, शीर्ष स्तर का कुल आकार q बंद 24 बाइट्स है, और यह q1_closure जो निहित टपल का प्रतिनिधित्व करता है को संदर्भित करता है:

q1_closure: 
    .quad (,)_static_info 
    .quad q3_closure+1 
    .quad q2_closure+1 
    .quad 3 
एक और 24 बाइट्स के लिए

q2 और q3 बंद बॉक्सिंग कर रहे हैं Int और Char और इतने दो quads (16 बाइट्स) प्रत्येक भाग ले सके। तो, q कुल 10 क्वाड, या 80 बाइट्स लेता है। (मुझे यह सुनिश्चित करने के लिए r एक सैनिटी चेक के रूप में शामिल किया गया था कि मैं किसी भी साझा जानकारी को गलत नहीं समझ रहा था।)

p टुपल के पास q1_closure, तो 7 क्वाड या 56 बाइट्स के बराबर मेमोरी पदचिह्न होगा।

संबंधित मुद्दे