Tôi đang cố gắng làm cho tinh thần từ hồ sơ của GHC. Có một ứng dụng khá đơn giản, sử dụng các thư viện werq
và lens-aeson
và trong khi tìm hiểu về hồ sơ GHC, tôi quyết định chơi với nó một chút.Có ý nghĩa từ hồ sơ GHC
Sử dụng các tùy chọn khác nhau (time
công cụ, +RTS -p -RTS
và +RTS -p -h
) Tôi đã nhận được số lượng sử dụng bộ nhớ khác nhau hoàn toàn. Có tất cả những con số đó, bây giờ tôi hoàn toàn mất việc cố gắng để hiểu những gì đang xảy ra, và bao nhiêu bộ nhớ ứng dụng thực sự sử dụng.
Tình huống này nhắc tôi cụm từ của Arthur Bloch: "Một người đàn ông với đồng hồ biết thời gian là gì. Một người đàn ông với hai chiếc đồng hồ không bao giờ chắc chắn."
Bạn có thể, hãy gợi ý cho tôi, cách tôi có thể đọc tất cả những con số đó và ý nghĩa của từng con số là gì.
Dưới đây là những con số:
time -l
báo cáo xung quanh 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
Sử dụng +RTS -p -RTS
báo cáo cờ xung quanh 92M. Mặc dù nó nói "tổng alloc" có vẻ như xa lạ với tôi, đó là một ứng dụng đơn giản như thế này có thể phân bổ và giải phóng 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
và hp2ps
cho tôi xem hình ảnh sau và hai con số: 114K trong tiêu đề và một cái gì đó xung quanh 1.8Mb trên biểu đồ.
Và, chỉ trong trường hợp, đây là ứng dụng:
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
UPDATE 1: Cảm ơn tất cả mọi người để được trả lời tốt đáng kinh ngạc. Như đã được đề xuất, tôi thêm đầu ra +RTS -s
, vì vậy toàn bộ hình ảnh sẽ được xây dựng cho tất cả những ai đọc nó.
#./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
UPDATE 2: Kích thước của thực thi:
#du -h simple-wreq
63M simple-wreq
Cảm ơn Zeta cho thư trả lời của bạn. Tôi có một câu hỏi nữa. Kích thước của nhị phân là 63M.Nó có nghĩa là nhị phân không được nạp đầy đủ vào bộ nhớ bằng cách nào đó? – Slabko
@Slabko: Tôi không có môi trường Unix để kiểm tra ngữ nghĩa của 'time -l' tại thời điểm này, do đó có thể không chính xác 100%. Tuy nhiên, tôi đã không tìm thấy bất kỳ trang man nào mà '-l' được mô tả. Bạn sử dụng 'time' nào? – Zeta
Tôi sử dụng Mac OS 10.11 và phiên bản được nhúng của 'time'. Nó sử dụng 'getrusage' của POSIX. Điều thú vị là, kích thước trả về 'getusage' trong kb và 19070976 kb là một con số thực sự lớn. Tôi đã thử GNU 'time' trên Linux; với kích thước nhị phân là 48M, nó vẫn cho rằng kích thước thiết lập tối đa là 32820Kb. Nhưng tôi nghĩ, tôi đã nhận được nhiều câu trả lời tốt cho câu hỏi của mình, và bây giờ tôi hiểu cách tôi nên đọc số hồ sơ GHC. Tôi không nghĩ rằng cách 'thời gian' hoạt động có liên quan đến sự hiểu biết về tối ưu hóa bộ nhớ Haskell trong trường hợp của tôi. Cảm ơn bạn rất nhiều vì sự giúp đỡ của bạn, tôi thực sự đánh giá cao nó! – Slabko