haskell - How to keep very big elements on memory without exhausting the garbage collector? -


in haskell, created vector of 1000000 intmaps. used gloss render picture in way accesses random intmaps vector.
is, had keep every single 1 of them in memory. rendering function lightweight, performance supposed good.
yet, program running @ 4fps. upon profiling, noticed 95% of time spent on gc. fair enough:
gc crazily scanning vector, though never changes.

is there way tell ghc "this big value needed , not change - not try collect inside it".

edit: program below sufficient replicate issue.

import qualified data.intmap map import qualified data.vector vec import graphics.gloss import graphics.gloss.interface.io.animate import system.random  main =     let size  = 10000000     let gen = map.fromlist $ zip [mod 10..0] [0..mod 10]     let vec   = vec.fromlist $ map gen [0..size]     let draw t =              rnd <- randomio :: io int             let empty = map.null $ vec vec.! mod rnd size             let rad   = if empty 10 else 50             return $ translate (20 * cos t) (20 * sin t) (circle rad)     animateio (inwindow "hi" (256,256) (1,1)) white draw 

this accesses random map on huge vector , draws rotating circle radius depend on whether map empty.
despite logic being simple, program struggles @ around 1 fps here.

gloss culprit here.

first, little background on ghc's garbage collector. ghc uses (by default) generational, copying garbage collector. means heap consists of several memory areas called generations. objects allocated youngest generation. when generation becomes full, scanned live objects , live objects copied next older generation, , generation scanned marked empty. when oldest generation becomes full, live objects instead copied new version of oldest generation.

an important fact take away gc ever examines live objects. dead objects never touched @ all. great when collecting generations garbage, happens in youngest generation. it's not if long-lived data undergoes many gcs, copied repeatedly. (it can counterintuitive used malloc/free-style memory management, allocation , deallocation both quite expensive, leaving objects allocated long time has no direct cost.)

now, "generational hypothesis" objects either short-lived or long-lived. long-lived objects end in oldest generation since alive @ every collection. meanwhile, of short-lived objects allocated never survive youngest generation; happen alive when collected promoted next generation. similarly, of short-lived objects promoted not survive third generation. result, oldest generation holds long-lived objects should fill slowly, , expensive collections have copy long-lived objects should occur rarely.

now, of true in program, except 1 problem:

    let displayfun backendref =             -- extract current time state             times           <- animatesr `getsioref` an.stateanimatetime              -- call user action animation frame             picture         <- frameop (double2float times)              renders         <- readioref rendersr             ports           <- viewstateviewport <$> readioref viewsr              windowsize      <- getwindowdimensions backendref              -- render frame             displaypicture                     windowsize                     backcolor                     renders                     (viewportscale ports)                     (applyviewporttopicture ports picture)              -- perform gc every frame try , avoid long pauses             performgc 

gloss tells gc collect oldest generation every frame!

this might idea if collections expected take less time delay between frames anyways, it's not idea program. if remove performgc call gloss, program runs quite quickly. presumably if let run long enough, oldest generation fill , might delay of few tenths of second gc copies long-lived data, that's better paying cost every frame.

all said, there ticket #9052 adding stable generation, suit needs nicely. see there more details.


Comments

Popular posts from this blog

c++ - Difference between pre and post decrement in recursive function argument -

php - Nothing but 'run(); ' when browsing to my local project, how do I fix this? -

php - How can I echo out this array? -