5.4. Patterns

5.4.1. Reducing memory usage

Yvo Smellenbergh

MegaPOV introduces a new patch named 'LESS_MEMORY_IN_PATTERNS_PATCH' to reduce the amount of memory needed for each pattern. This is done by replacing the structs in the union Vals by pointers. The original size of Vals was about 104 bytes, occupied by the crackle pattern.

By using pointers, the size is reduced to 4 bytes plus the size of the data required for a specific pattern. If for example Function pattern is used, the size of Vals is 4 plus the size for the 2 pointers which is 8. This total of 12 is a whole lot less than the original 104! This patch will increase the amount of memory used if only crackle is used. However, this is unlikely to happen.

5.4.1.1. Adding new patterns

Because MegaPOV is designed to turn on and off each patch separately, you must be careful whenever a patch is added. This patch changes many parts of the code and especially the definition of TPATTERN_FIELDS is a bit tricky. For example, the ANGLE_OF_INCIDENCE_PATCH is added to the TPATTERN_FIELDS definition like this in frame.h. First you define it like this:

#ifdef ANGLE_OF_INCIDENCE_PATCH
  #ifdef LESS_MEMORY_IN_PATTERNS_PATCH
    typedef struct  {  VECTOR AOI_origin;  unsigned char pt_fixed;
    }AOI, *AOIPTR ;
    #define AngleOfIncidenceDef  AOIPTR Aoi;
  #else
   #define AngleOfIncidenceDef struct { VECTOR AOI_origin; unsigned char pt_fixed; } Aoi;
  #endif
#else //ANGLE_OF_INCIDENCE_PATCH
  #define AngleOfIncidenceDef
 #endif

and then add it to the TPATTERN_FIELDS definition like this:

#define TPATTERN_FIELDS       \
 unsigned short Type, Wave_Type, Flags; \
 :            \
 union {                     \
   DENSITY_FILE *Density_File; \
   : \
   AngleOfIncidenceDef \
   : \
   ProjectionDef \
 } Vals;

AngleOfIncidenceDef is always defined to avoid two definitions for TPATTERN_FIELDS. If ANGLE_OF_INCIDENCE_PATCH isn't defined, AngleOfIncidenceDef is empty and is ignored, if ANGLE_OF_INCIDENCE_PATCH is defined, AngleOfIncidenceDef is a pointer or a struct, depending on whether LESS_MEMORY_IN_PATTERNS_PATCH is defined or not.

This leaves us with the problem of accessing the members of the members of Vals. In frame.h LESS_MEMORY_PATCH_MO is defined like this:

#ifdef LESS_MEMORY_IN_PATTERNS_PATCH
  #define LESS_MEMORY_PATCH_MO ->
#else
  #define LESS_MEMORY_PATCH_MO .
#endif

Whenever you access a member from an element of Vals you use

New->Vals.Crackle LESS_MEMORY_PATCH_MO lastseed = 0x8000000;

which results in

New->Vals.Crackle.lastseed = 0x8000000;
or
New->Vals.Crackle->lastseed = 0x8000000;

depending on the state of the switch LESS_MEMORY_IN_PATTERNS_PATCH.

For each pattern added, which uses a pointer, memory is allocated in the following functions:

  • parstxtr.cpp - Parse_Pattern();
  • pattern.cpp - Copy_TPat_Fields();

Memory is freed for each new pattern in:

  • pattern.cpp - Destroy_TPat_Fields();

The best way to find all necessary changes is to find all occurrences of one patch and take a look on how it is implemented.