2016-10-14 8 views
5

से समझ बनाना मैं जीएचसी प्रोफाइलर से समझने की कोशिश कर रहा हूं। एक आसान ऐप है, जो werq और lens-aeson पुस्तकालयों का उपयोग करता है, और जीएचसी प्रोफाइलिंग के बारे में सीखते समय, मैंने थोड़ा सा खेलने का फैसला किया।जीएचसी प्रोफाइलर

विभिन्न विकल्पों का उपयोग (time उपकरण, +RTS -p -RTS और +RTS -p -h) मैंने अपनी मेमोरी उपयोग की पूरी तरह से अलग संख्या हासिल की। उन सभी संख्याओं के साथ, अब मैं समझने की कोशिश कर रहा हूं कि क्या हो रहा है, और ऐप वास्तव में कितनी मेमोरी का उपयोग करता है।

यह स्थिति मुझे आर्थर ब्लोच द्वारा वाक्यांश की याद दिलाती है: "घड़ी वाला एक आदमी जानता है कि यह कितना समय है। दो घड़ियों वाले एक आदमी को कभी यकीन नहीं है।"

क्या आप कृपया मुझे सुझाव दे सकते हैं कि मैं उन सभी संख्याओं को कैसे पढ़ सकता हूं, और उनमें से प्रत्येक का क्या अर्थ है। 19M

#/usr/bin/time -l ./simple-wreq 
... 
     3.02 real   0.39 user   0.17 sys 
    19070976 maximum resident set size 
     0 average shared memory size 
     0 average unshared data size 
     0 average unshared stack size 
    21040 page reclaims 
     0 page faults 
     0 swaps 
     0 block input operations 
     0 block output operations 
     71 messages sent 
     71 messages received 
     2991 signals received 
     43 voluntary context switches 
     6490 involuntary context switches 

आसपास

time -l रिपोर्ट +RTS -p -RTS झंडा रिपोर्ट चारों ओर 92M का उपयोग करना:

यहाँ नंबर दिए गए हैं। हालांकि यह कहते हैं, "कुल alloc" यह मेरे लिए अजीब लगता है, कि इस तरह एक सरल अनुप्रयोग का आवंटन और जारी कर सकते हैं 91M

# ./simple-wreq +RTS -p -RTS  
# cat simple-wreq.prof 
     Fri Oct 14 15:08 2016 Time and Allocation Profiling Report (Final) 

      simple-wreq +RTS -N -p -RTS 

     total time =  0.07 secs (69 ticks @ 1000 us, 1 processor) 
     total alloc = 91,905,888 bytes (excludes profiling overheads) 

COST CENTRE        MODULE       %time %alloc 

main.g         Main        60.9 88.8 
MAIN         MAIN        24.6 2.5 
decodeLenient/look      Data.ByteString.Base64.Internal 5.8 2.6 
decodeLenientWithTable/fill    Data.ByteString.Base64.Internal 2.9 0.1 
decodeLenientWithTable.\.\.fill   Data.ByteString.Base64.Internal 1.4 0.0 
decodeLenientWithTable.\.\.fill.\  Data.ByteString.Base64.Internal 1.4 0.1 
decodeLenientWithTable.\.\.fill.\.\.\.\ Data.ByteString.Base64.Internal 1.4 3.3 
decodeLenient       Data.ByteString.Base64.Lazy  1.4 1.4 


                              individual  inherited 
COST CENTRE            MODULE       no.  entries %time %alloc %time %alloc 

MAIN              MAIN        443   0 24.6 2.5 100.0 100.0 
main             Main        887   0 0.0 0.0 75.4 97.4 
    main.g             Main        889   0 60.9 88.8 75.4 97.4 
    object_            Data.Aeson.Parser.Internal  925   0 0.0 0.0  0.0 0.2 
    jstring_            Data.Aeson.Parser.Internal  927   50 0.0 0.2  0.0 0.2 
    unstream/resize          Data.Text.Internal.Fusion   923   600 0.0 0.3  0.0 0.3 
    decodeLenient           Data.ByteString.Base64.Lazy  891   0 1.4 1.4 14.5 8.1 
    decodeLenient          Data.ByteString.Base64   897   500 0.0 0.0 13.0 6.7 
.... 

+RTS -p -h और hp2ps मुझे निम्न चित्र और दो नंबर दिखाने: शीर्षक में 114K और ग्राफ पर 1.8 एमबी के आसपास कुछ।

module Main where 

import Network.Wreq 
import Control.Lens 
import Data.Aeson.Lens 
import Control.Monad 

main :: IO() 
main = replicateM_ 10 g 
    where 
    g = do 
     r <- get "http://httpbin.org/get" 
     print $ r ^. responseBody 
        . key "headers" 
        . key "User-Agent" 
        . _String 

अद्यतन: 1: Memory Profiling

और, मामले में, यहाँ अनुप्रयोग है अविश्वसनीय अच्छा प्रतिक्रिया के लिए हर किसी को धन्यवाद। जैसा कि सुझाव दिया गया था, मैं +RTS -s आउटपुट जोड़ता हूं, इसलिए पूरी तस्वीर इसे पढ़ने वाले सभी के लिए तैयार होती है।

#./simple-wreq +RTS -s 
... 
    128,875,432 bytes allocated in the heap 
     32,414,616 bytes copied during GC 
     2,394,888 bytes maximum residency (16 sample(s)) 
     355,192 bytes maximum slop 
       7 MB total memory in use (0 MB lost due to fragmentation) 

            Tot time (elapsed) Avg pause Max pause 
    Gen 0  194 colls,  0 par 0.018s 0.022s  0.0001s 0.0022s 
    Gen 1  16 colls,  0 par 0.027s 0.031s  0.0019s 0.0042s 

अद्यतन 2: निष्पादन का आकार:

#du -h simple-wreq 
63M  simple-wreq 

उत्तर

7

घड़ी वाला एक आदमी जानता है कि यह कितना समय है। दो घड़ियों वाला एक आदमी कभी यकीन नहीं करता है।

आह, लेकिन दो घड़ियों क्या दिखाती हैं? क्या दोनों यूटीसी में वर्तमान समय दिखाना चाहते हैं? या उनमें से एक यूटीसी में समय दिखाना है, और दूसरी बार मंगल ग्रह पर एक निश्चित बिंदु पर? जब तक वे सिंक हो जाते हैं, दूसरा परिदृश्य कोई समस्या नहीं होगी, है ना?

और यह वही है जो यहां हो रहा है। आप अलग अलग स्मृति माप की तुलना:

  • अधिकतम निवास
  • आबंटित स्मृति की कुल राशि

अधिकतम निवास स्मृति की सबसे अधिक राशि अपने कार्यक्रम को किसी पर उपयोग करता है पहर। वह 1 9 एमबी है। हालांकि, आवंटित स्मृति की कुल राशि बहुत अधिक है, क्योंकि जीएचसी कैसे काम करता है: यह उन वस्तुओं के लिए "आवंटित" स्मृति है जो कचरा इकट्ठा होते हैं, जो लगभग हर चीज है जो अनपॅक नहीं होती है।

हमें इस के लिए एक सी उदाहरण का निरीक्षण करते हैं:

int main() { 
    int i; 
    char * mem; 

    for(i = 0; i < 5; ++i) { 
     mem = malloc(19 * 1000 * 1000); 
     free(mem); 
    } 
    return 0; 
} 

जब भी हम malloc उपयोग करें, हम स्मृति के 19 मेगाबाइट आवंटित करेगा। हालांकि, हम तुरंत बाद मेमोरी मुक्त करते हैं। हमारे पास एक बिंदु पर अब तक की अधिकतम मात्रा में स्मृति 1 9 मेगाबाइट है (और ढेर के लिए थोड़ा और प्रोग्राम स्वयं)।

हालांकि, कुल मिलाकर, हम 5 * 1 9 एम, 95M कुल आवंटित करते हैं। फिर भी, हम अपने छोटे कार्यक्रम को सिर्फ 20 मेगा रैम जुर्माना के साथ चला सकते हैं। कुल आवंटित स्मृति और अधिकतम निवास के बीच यह अंतर है। ध्यान दें कि समय के अनुसार रिपोर्ट की गई निवास हमेशा कम से कम du <executable> होती है, क्योंकि उसे स्मृति में भी रहना पड़ता है।

कहा जा रहा है कि आंकड़े उत्पन्न करने का सबसे आसान तरीका -s है, जो दिखाएगा कि हास्केल के कार्यक्रम बिंदु से अधिकतम निवास क्या था। आपके मामले में, यह 1.9M होगा, आपकी ढेर प्रोफ़ाइल में संख्या (या प्रोफाइलिंग के कारण राशि को दोगुना करें)। और हाँ, हास्केल निष्पादन योग्य बहुत बड़े होते हैं, क्योंकि पुस्तकालय स्थिर रूप से जुड़े होते हैं।

+0

आपके उत्तर के लिए जेता धन्यवाद। मेरे पास एक और प्रश्न है। बाइनरी का आकार 63 मीटर है।क्या इसका मतलब यह है कि बाइनरी किसी भी तरह स्मृति में पूरी तरह से लोड नहीं किया गया था? – Slabko

+0

@ स्लैब्को: मेरे पास इस समय 'टाइम-एल' के अर्थशास्त्र की जांच करने के लिए यूनिक्स वातावरण नहीं है, इसलिए यह 100% सही नहीं हो सकता है। हालांकि, मुझे कोई वास्तविक मैन पेज नहीं मिला है जहां '-l' वर्णित है। आप किस समय का उपयोग करते हैं? – Zeta

+0

मै मैक ओएस 10.11 और 'टाइम' के एम्बेडेड संस्करण का उपयोग करता हूं। यह पॉज़िक्स के 'गेट्रेजेज' का उपयोग करता है। दिलचस्प बात यह है कि, केबी में 'गेटुसेज' रिटर्न आकार और 1 9 7070 9 76 केबी वास्तव में बड़ी संख्या है। मैंने लिनक्स पर जीएनयू 'टाइम 'की कोशिश की; 48 एम के बाइनरी आकार के साथ यह अभी भी दावा करता है कि अधिकतम निवासी सेट आकार 32820 केबी के बराबर है लेकिन मुझे लगता है कि मुझे अपने प्रश्न के लिए अच्छा जवाब मिला है, और अब मैं समझता हूं कि मुझे जीएचसी प्रोफाइलर की संख्या कैसे पढ़नी चाहिए। मुझे नहीं लगता कि जिस तरह से 'टाइम' काम मेरे मामले में हास्केल मेमोरी ऑप्टिमाइज़ेशन की समझ के लिए प्रासंगिक है। आपकी मदद के लिए बहुत बहुत धन्यवाद, मैं वास्तव में इसकी सराहना करता हूं! – Slabko

4

time -l प्रदर्शित कर रहा है (निवासी, यानी बदली नहीं) के रूप में (जाहिर है) ऑपरेटिंग सिस्टम के द्वारा देखा प्रक्रिया का आकार । इसमें हास्केल ढेर के अधिकतम आकार (जीएचसी के जीसी काम करने के तरीके के कारण), साथ ही आरटीएस या अन्य सी पुस्तकालयों द्वारा आवंटित कुछ भी शामिल है, साथ ही आपके निष्पादन योग्य कोड के साथ-साथ पुस्तकालयों पर निर्भर करता है। इस मामले में अनुमान लगा रहा हूं कि 1 9 एम में प्राथमिक योगदानकर्ता आपके निष्कर्ष का आकार है।

total alloc हास्केल ढेर पर आवंटित कुल राशि है। यह अधिकतम ढेर आकार का एक माप नहीं है (जो आम तौर पर लोगों का मतलब है "मेरे प्रोग्राम का उपयोग कितना मेमोरी है")। आवंटन बहुत सस्ता है और लगभग 1 जीबी/एस की आवंटन दर हास्केल कार्यक्रम के लिए विशिष्ट हैं।

एचपी 2पीएस आउटपुट के शीर्षलेख में संख्या "114,272 बाइट्स x सेकंड" कुछ अलग है: यह ग्राफ का अभिन्न अंग है, और बाइट्स में नहीं, बाइट्स * सेकंड में मापा जाता है। उदाहरण के लिए यदि आपका प्रोग्राम 4 सेकंड के लिए 10 एमबी संरचना पर रखता है तो इससे 40 एमबी * एस तक बढ़ने का कारण बन जाएगा।

संख्या के आसपास 1.8 ग्राफ में दिखाया गया एमबी हास्केल ढेर, जो शायद नंबर पर आप सबसे रुचिकर है की वास्तविक अधिकतम आकार है।

आप के बारे में संख्याओं का सबसे अधिक उपयोगी स्रोत हटा दिया है आपके प्रोग्राम का निष्पादन, जो +RTS -s के साथ चल रहा है (इसे प्रोफाइलिंग के साथ भी बनाया जाना आवश्यक नहीं है)।