Using SCATTER .. NAME .. ADDITIVE for reducing system load in inner loops

I Love Xbase++ (ILX)
The portal for Xbase++ developers worldwide

Till Warweg

Member
Staff member
I am here to help you!
Feb 1, 2021
38
11
8
Customer Identifier
E074775
The command SCATTER .. NAME provides an easy way for loading the values in the fields of a table into a data object. For example, for transforming values using certain criteria and the writing the data back to the table using GATTER .. NAME.

Care must be taken, however, if SCATTER .. NAME is used in an inner loop. Because the command creates a new data object by default, a fast running loop can easily produce a high system load and can even result in runtime errors due to memory/handle exhaustion.

Xbase++:
////////////////////////////////////////////
// WRONG/MEMORY EXHAUSTIVE CODE
////////////////////////////////////////////
LOCAL oData

  USE orderposition NEW
  USE orderposition_new  NEW

  DO WHILE .NOT. orderposition->(EOF())
      SCATTER NAME oData IN orderposition
      oData:price *= nFactor
 
      orderposition_new->(DbAppend())
      GATHER NAME oData IN orderposition_new

      orderposition->(DbSkip())
  ENDDO

In the above code snippet, order positions are successively read into a data object, manipulated and then appended to a new table. In each iteration, a new data object is created in SCATTER .. NAME, which depending on the structure of the table "orderposition", may have many member variables storing the field values. This together with the fact that the loop runs uninterrupted produces a high memory/handle consumption and may easily swamp the garbage collector.

A better approach is using the ADDITIVE option of SCATTER .. NAME. This causes an existing data object to be reused in the operation, and results in a constant resource load in the above scenario. Also, the code runs faster because the data object's member list remains constant and does not need to be recreated in each iteration of the loop.

Xbase++:
////////////////////////////////////////////
// CORRECTED CODE
////////////////////////////////////////////
LOCAL oData

  USE orderposition NEW
  USE orderposition_new  NEW

  DO WHILE .NOT. orderposition->(EOF())
      // Use ADDITIVE option for reusing data objects in the loop
      SCATTER NAME oData IN orderposition ADDITIVE
      oData:price *= nFactor
 
      orderposition_new->(DbAppend())
      GATHER NAME oData IN orderposition_new

      orderposition->(DbSkip())
  ENDDO


See also:
Xbase++ documentation Command SCATTER NAME
 
Last edited: