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”