packages feed

leancheck-0.9.2: bench/memory-usage.hs

-- memory-usage.hs -- example program illustrating a limitation of LeanCheck
--
-- Copyright (c) 2020 Rudy Matela.
-- Distributed under the 3-Clause BSD licence (see the file LICENSE).
--
-- Many thanks to Jonas Duregard for providing this example.
--
-- If we set the test limit to millions of values, memory consumption may be
-- too high.  This is aggravated depending on how tests are ordered.
--
-- See below.
import Test.LeanCheck
import Data.Int
import Data.Word

-- dummy property that is always 'True' for a correct 'Num' instance.
evenOrOdd :: (Listable a, Show a, Integral a) => [a] -> Bool
evenOrOdd xs  =  all (\x -> odd x || even x) xs

main :: IO ()
main = do

  -- With just the following 10 lines
  -- this program consumes around 500 Mb of memory.
  -- At the end of each checkFor call
  -- the underlying tiers/list is garbage collected.
  checkFor 1000000 (evenOrOdd :: [Int]     -> Bool)
  checkFor 1000000 (evenOrOdd :: [Int8]    -> Bool)
  checkFor 1000000 (evenOrOdd :: [Int16]   -> Bool)
  checkFor 1000000 (evenOrOdd :: [Int32]   -> Bool)
  checkFor 1000000 (evenOrOdd :: [Int64]   -> Bool)
  checkFor 1000000 (evenOrOdd :: [Word]    -> Bool)
  checkFor 1000000 (evenOrOdd :: [Word8]   -> Bool)
  checkFor 1000000 (evenOrOdd :: [Word16]  -> Bool)
  checkFor 1000000 (evenOrOdd :: [Word32]  -> Bool)
  checkFor 1000000 (evenOrOdd :: [Word64]  -> Bool)

  -- However, if the following 10 lines are uncommented
  -- we increase memory consumption.
  -- Turns out the GC will not trigger as Haskell sees it will still use
  -- enumerated values, so it tries to keep values in memory.
  -- The maximum resident set size will increase to 3 000 Mb.
  {-
  checkFor 1000000 (evenOrOdd :: [Int]     -> Bool)
  checkFor 1000000 (evenOrOdd :: [Int8]    -> Bool)
  checkFor 1000000 (evenOrOdd :: [Int16]   -> Bool)
  checkFor 1000000 (evenOrOdd :: [Int32]   -> Bool)
  checkFor 1000000 (evenOrOdd :: [Int64]   -> Bool)
  checkFor 1000000 (evenOrOdd :: [Word]    -> Bool)
  checkFor 1000000 (evenOrOdd :: [Word8]   -> Bool)
  checkFor 1000000 (evenOrOdd :: [Word16]  -> Bool)
  checkFor 1000000 (evenOrOdd :: [Word32]  -> Bool)
  checkFor 1000000 (evenOrOdd :: [Word64]  -> Bool)
  -}

  -- This is a limitation of LeanCheck
  -- that comes from using simple lists of lists
  -- as the means for enumeration.