Ticket #22 (closed defect: invalid)

Opened 3 years ago

Last modified 3 years ago

Excessive memory allocation when using mutable vectors

Reported by: babusri Owned by:
Priority: critical Milestone: 0.7.1
Version: 0.6 Keywords:
Cc:

Description

With the length of the mutable vector fixed, I expected that the memory allocated on the heap wouldn't increase with number of vector operations performed. But I see a linear increase. I think I am not using the vector package properly. I didn't see an option to ask a question and so I am raising it here.

I asked this question in the irc (http://hpaste.org/fastcgi/hpaste.fcgi/view?id=25743) and copumpkin asked me to use Data.Vector.Unboxed.Mutable instead of Data.Vector.Mutable. It improved the bytes copied during gc, but not memory allocation. For e.g. if I duplicate the replicateM_ line, memory allocation doubles.

Change History

Changed 3 years ago by rl

It seems that hpaste.org is down. Could you please add your program to the ticket.

Changed 3 years ago by rl

{-
Question: Using Data.Vector.Mutable and a Vector lfsr of 16 Word32, I call a function f several times with arg lfsr. f modifes the values of lfsr. Works fine but sstderr reports 46 Meg allocated on heap and 65 meg copied during GC. If I call f fewer times, less is allocated on heap in a linear fashion. As I am supposedly creating only one vector and modifying contents in place, why is so much space being allocated?

vperf.exe +RTS -sstderr
"100000"
      46,195,412 bytes allocated in the heap
      65,082,528 bytes copied during GC
      15,391,872 bytes maximum residency (5 sample(s))
       1,349,892 bytes maximum slop
              31 MB total memory in use (0 MB lost due to fragmentation)

  Generation 0:    76 collections,     0 parallel,  0.23s,  0.22s elapsed
  Generation 1:     5 collections,     0 parallel,  0.11s,  0.19s elapsed

  Parallel GC work balance: -1.#J (0 / 0, ideal 1)

  INIT  time    0.02s  (  0.00s elapsed)
  MUT   time    0.09s  (  0.08s elapsed)
  GC    time    0.34s  (  0.41s elapsed)
  EXIT  time    0.00s  (  0.00s elapsed)
  Total time    0.45s  (  0.48s elapsed)
  %GC time      75.9%  (83.9% elapsed)
  Alloc rate    422,358,052 bytes per MUT second
  Productivity  20.7% of total user, 19.4% of total elapsed
-}

{-
  Using ghc 6.12.1 on WinXP.
  Compiled using
  ghc -threaded -Odph -fvia-C -funbox-strict-fields -optc-O2 -optc-march=pentium4 -optc-ffast-math --make vperf.hs
-}

import Control.Monad
import qualified Data.Vector.Mutable as M
import Data.Word

main = do
  lfsr <- M.newWith 16 (0::Word32)
  let iter = 100000
  replicateM_ iter (f1 lfsr)
  r <- M.read lfsr 15
  M.clear lfsr
  print $ show r


-- dummy function to modify array values in place
f1 lfsr =
  Control.Monad.forM_ [0..15]
             (\i -> do
                val <- M.read lfsr i
                M.write lfsr i (val + 1))

Changed 3 years ago by rl

  • priority changed from minor to critical
  • milestone set to 0.8

Changed 3 years ago by rl

  • milestone changed from 0.8 to 0.7.1

Changed 3 years ago by rl

  • status changed from new to closed
  • resolution set to invalid

It turns out that the program allocates huge thunks for val+1. Changing the last line to

W.write lfsr i $! val + 1

makes it run in constant memory as expected.

Note: See TracTickets for help on using tickets.