Logo

Hacker’s Guide to Visual FoxPro
An irreverent look at how Visual FoxPro really works. Tells you the inside scoop on every command, function, property, event and method of Visual FoxPro.

SET BLOCKSIZE, Set(“Blocksize”), Sys(2012)

BLOCKSIZE specifies the size of the individual blocks used to store memo and general field data for the current DataSession. SYS(2012) reports on what setting is in effect for an individual file.

Usage

SET BLOCKSIZE TO nSize
nSizeInBytes = SET( "BLOCKSIZE" )
nSizeInBytes = SYS( 2012 [, nArea | cAlias ] )

Parameter

Value

Meaning

nSize

0

Specifies that memo fields are stored in blocks of one byte.

1–32

Specifies that memo fields are stored in large blocks of nSize times 512 bytes, that is, blocks ranging from 512 bytes to 16 kilobytes.

33–32,768

Specifies that memo field disk space is allocated in blocks of nSize bytes.

nArea

Numeric

Specifies the work area for the table to be examined.

Omitted

If cAlias is also omitted, the table in the current work area is examined.

cAlias

Character

Specifies the table alias to report on.

Omitted

If nArea is also omitted, the table within the current work area is examined.

nSizeInBytes

Numeric

The current blocksize in bytes, or zero if no memo field exists in the current work area.

BLOCKSIZE can have quite an effect on the size of your application, especially if several VCXs and SCXs are included in the final EXE. Visual FoxPro uses memo field blocks like they’re going out of style. When editing data in shared tables, every time the contents of a memo field are changed, the entire contents of that memo field are written out again to the end of the file, and the original blocks used to store the data are flagged as unused. This space is not reclaimed by Visual FoxPro until the file is re-COPY’d or PACK’d (we prefer the former). In the less common case of using a file exclusively, additional blocks are allocated only once the current block has been completely filled.

The choice of BLOCKSIZE is one that varies depending on the exact circumstances in which you’re using the memo field. One-byte blocks are the most efficient for space storage, if that is the overriding consideration. There must be a small amount of overhead in using single-byte blocks, we’re sure, and under some circumstances (like editing multi-megabyte general fields), that overhead could become the most significant factor. If, on the other hand, you expect to store, and not edit, small memos of a predictable size, it probably makes more sense to allocate blocks in a multiple of the most common size, say, 64-byte blocks if most memos are 128 bytes or less. The performance of your hardware, both in the storage and retrieval of blocks, as well as the CPU overhead in tracking them all, could be the most important factor in other cases. Our advice: your mileage may vary. Test the file’s BLOCKSIZE under the hardware conditions and with the data it will be storing, and benchmark its performance.

SET(“BLOCKSIZE”) is the current setting and has nothing to do with individual tables. Each individual table’s block size is stored in the header of the memo file, and may be retrieved with SYS(2012). The SET command only comes into play for tables (and cursors) created or rewritten within this data session. This is dumb—we think that block size should be settable for each individual table.

Another annoying thing about these functions is that since SYS(2012) always returns its value in bytes, but SET BLOCKSIZE uses three different schemes—blocks of 512 bytes for 1–32, explicit bytes for 33–32,768 and zero for one byte—the routine to decode them and calculate what value you want to pass to SET BLOCKSIZE seems like a pain. It isn’t, really. If you originally SET BLOCKSIZE TO 32, then used SYS(2012) to obtain the current setting (16384) and then reissued SET BLOCKSIZE with the 16384 figure, the effect would be the same. The only gotcha is if SET(“BLOCKSIZE”) is zero, then SYS(2012) would return a 1. So, the function to return the appropriate BLOCKSIZE from a SYS(2012) value would be:

lcSetBlockSize = IIF(SYS(2012) = 1, 0, SYS(2012))

A table retains its block size unless it is rewritten while there is a different block size in effect. A number of commands can cause this: ALTER TABLE, COPY, CREATE TABLE, MODIFY STRUCTURE, PACK, or even SELECT … INTO TABLE. Like most SET commands, our preference is to decide the right way it should be throughout your application, set it that way, and leave it alone.

Example

SET BLOCKSIZE TO 0
? SYS( 2012 )   && returns the block size of the current file
? SET( "BLOCKSIZE" )  && returns the global or datasession-
                      && specific setting

See Also

Alter Table, Copy To, Create Table, Pack, Set DataSession