Heartbeat: Garbage collection in VFP and .NET are similar
VFP stores user defined names such as variable, field, property, class and procedure names in a table.
When the name table runs out of space, the GC begins. All the entries are marked as unused. Then all the various name table clients are sent a message to flag their names as used. These clients include the object manager, the database engine, the variable manager, and the compiled code manager. The remaining names that are marked as unused are purged from the table.
This algorithm is very much like the .NET garbage collector. There is no reference counting of names, and unused names cannot be referenced. However, since there are no references or pointers, the GC is much simpler in VFP.
You can see the effect of the garbage collection by timing how long it takes to run a loop that creates and discards batches of unique names.
Run the code below, and you’ll get a heartbeat EKG on your screen. You might need to adjust the scaling factors depending on the performance of your machine. The x axis is time and the y axis is the amount of time it takes per batch
The resulting graph shows how long it takes to add bunches of 10,000 names to the table. The time varies periodically, repeating about every 6 batches. If each bunch took exactly the same amount of time, the graph would be flat (and the heart would not be beating).
As the name table fills, it takes longer to add a name. When the table is full, a garbage collection is done, which clears out much of the table.
Repetition occurs about every 6 batches because the name table size is around 65000 names, and not every name is garbage when the collection occurs.
Let’s become cardiologists and examine the shape of the heartbeat. The lowest part of the EKG is actually the batch that took the longest time (highest numerical value since the origin is the top left of the screen). After the name table has been garbage collected, it’s mostly empty. As it gets filled, the time per batch increases.
CLEAR
x0=0
y0=0
nPrior=0
SET DECIMALS TO 3
CREATE CURSOR results (x i,nsecs b,delta b)
BROWSE LAST nowait
FOR i = 1 TO 200
nsec=SECONDS() && start time
num=5000
usenames(i,num)
ntime=SECONDS()-nsec && end time
nval=ntime-nPrior && delta (# of names/sec)
* ?i,ntime,ntime,nval
y1=ntime*3000 &&+_screen.Height/2 &&scale to fit in middle of screen
x1=i*4 && scale x to show better
INSERT INTO results VALUES (i,ntime,nval)
_screen.Line(x0,y0,x1,y1) && draw a line to connect dots
x0=x1 && advance prior point
y0=y1
nPrior=ntime && and prior value
ENDFOR
PROCEDURE usenames(base,n)
LOCAL i
FOR i = 1 TO n
cvar="x"+PADL(base,3,"0")+TRANSFORM(i) && create a unique var name like "x0011"
STORE i TO (cvar) && create the var
ENDFOR
RETURN && vars get released when they go out of scope
48919
Comments
- Anonymous
January 28, 2005
Hello Calvin
1st i want to thank you for clearing up a few things the vfp-community has been dying to know for a while. i constantly see discussions about items like 'the m dot thingy' or the garbage collection.
your test code is very interesting and educational (i had to change the number of variables created from 5000 to 2000 as i work with vfp6.
now, i got a question: is it possible to clear that name-table; to release all unused entries?
i tried several different release mechanisms like 'release all like x*', etc, but no success.
i got a feeling there is no way. if this is correct, would that be a functionality to add to any future advancement made to vfp?
again, thanks for your educational blogs. - Anonymous
March 15, 2006
In this post: Heartbeat: Garbage collection in VFP and .NET are similar, I talked about how the VFP name... - Anonymous
April 11, 2008
Writing programs using .Net is very productive. One reason is because much of memory management is “managed”