开发者

No error message in Haskell

开发者 https://www.devze.com 2023-04-07 02:03 出处:网络
Just out of curiosity, I made a simple script to check speed and memory efficiency of constructing a list in Haskell:

Just out of curiosity, I made a simple script to check speed and memory efficiency of constructing a list in Haskell:

wasteMem :: Int -> [Int]
wasteMem 0 = [199]
wasteMem x = (12432483483467856487256348746328761:wasteMem (x-1))

main = do
    putStrLn("hello")
    putStrLn(show (wasteMem 10000000000000000000000000000000000))

The strange thing is, when I tried this, it didn't run out of memory or stack space, it开发者_运维问答 only prints [199], the same as running wasteMem 0. It doesn't even print an error message... why? Entering this large number in ghci just prints the number, so I don't think it's a rounding or reading error.


Your program is using a number greater than maxBound :: Int32. This means it will behave differently on different platforms. For GHC x86_64 Int is 64 bits (32 bits otherwise, but the Haskell report only promises 29 bits). This means your absurdly large value (1x10^34) is represented as 4003012203950112768 for me and zero for you 32-bit folks:

GHCI> 10000000000000000000000000000000000 :: Int
4003012203950112768
GHCI> 10000000000000000000000000000000000 :: Data.Int.Int32
0

This could be made platform independent by either using a fixed-size type (ex: from Data.Word or Data.Int) or using Integer.

All that said, this is a poorly conceived test to begin with. Haskell is lazy, so the amount of memory consumed by wastedMem n for any value n is minimal - it's just a thunk. Once you try to show this result it will grab elements off the list one at a time - first generating "[12432483483467856487256348746328761, and leaving the rest of the list as a thunk. The first value can be garbage collected before the second value is even considered (a constant-space program).


Adding to Thomas' answer, if you really want to waste space, you have to perform an operation on the list, which needs the whole list in memory at once. One such operation is sorting:

print . sort . wasteMem $ (2^16)

Also note that it's almost impossible to estimate the run-time memory usage of your list. If you want a more predictable memory benchmark, create an unboxed array instead of a list. This also doesn't require any complicated operation to ensure that everything stays in memory. Indexing a single element in an array already makes sure that the array is in memory at least once.

0

精彩评论

暂无评论...
验证码 换一张
取 消