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.








CREATE CURSOR results (x i,nsecs b,delta b)


FOR i = 1 TO 200

      nsec=SECONDS()    && start time



      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


      nPrior=ntime      && and prior value



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


RETURN && vars get released when they go out of scope




Comments (3)
  1. Gunnar Philipp says:

    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.

  2. In this post: Heartbeat: Garbage collection in VFP and .NET are similar, I talked about how the VFP name…

  3. Writing programs using .Net is very productive. One reason is because much of memory management is “managed”

Comments are closed.

Skip to main content