[clean-list] finding and curing a Space Leak

Erik Zuurbier F.S.A.Zuurbier@inter.nl.net
Sat, 18 Nov 2000 18:15:57 +0100 (MET)


Dear all,

The sample program below (Clean 1.3.2, 0.8 IO-library) accumulates
statistics, which it prints when the quit-menu-item is selected. If you
show the garbage collections, you see that heap continues to grow. The
program does not actually carry out the statistics updates as it goes.
Instead it just throws all the unfinished calculations on the heap.
Rightfully so, but it is not what I want. I want the program to actually do
the update in each iteration. No lazyness wanted here.

The original program is much bigger, we don't have a proper debugger, and
the heap profiler leaves much to be desired. (See for instance the two pass
heap profiler of Runciman.)

So I spent ages locating this space leak. I then found that it can be cured
by replacing the line marked // ## by the two lines /* commented out */.
However, I find the result very ugly: having to introduce an extra variable
(v1) just to force evaluation. Is there a nicer way?

Other question: I wanted to make the Counts type more unique, like this:
:: *Counts	:== *{!*(!Real,!Int)}
I could not find a way to get the program past the type checker though.
Does anybody know how?

Regards Erik Zuurbier

=============================


module SpaceLeak
import StdEnv,deltaTimer, deltaIOState, deltaEventIO

:: *Counts	:== *{!(!Real,!Int)}
:: *State	= {counts :: !Counts, list :: [(Int,Real)]}

Start w
	# ({counts},_) = StartIO [MenuSystem [file],timer] iSta [] w
	= counts
timer	=: TimerSystem [Timer 1 Able 0 upd]

upd _ sta=:{counts,list=list=:[(i,x):rest]} io
	#! (y,j)  = counts.[i]
	#  sta = {sta & counts = {counts & [i] = ((y-x)*0.9+x,j)}} // ##
	#  sta = {sta & list = rest}
	=  (sta,io)
/*
	#! v1	= (y-x)*0.9+x
	#  sta	= {sta & counts = {counts & [i] = (v1,j)}}
*/

// Unimportant stuff below

file	=: PullDownMenu 1 "File" Able
       		[MenuItem 1 "Quit" (Key 'Q') Able quitIO]

quitIO sta io = (sta, QuitIO io)

iSta = {counts = {(0.0,0) \\ i <- [0..9]}, list = samples}

samples = zip2 (fr [0..9]) (fr [2.1, 2.5 .. 10.0])

fr as = (flatten o repeat) as