7.5 Controlling Memory Usage

7.5.1 The HOOPS Memory Manager

The dynamic allocation and releasing of memory in HOOPS/3DGS is controlled by an internal memory manager. The memory manager may allocate memory in numerous situations, such as when objects are inserted into the HOOPS database, an Update_Display is performed or files are loaded into the HOOPS database. As items are removed from the HOOPS database, the memory manager takes care of the freeing of the memory associated with them. HOOPS allocates memory and chunks and attempts to retain/reuse them after items are deleted.

HOOPS does not monitor the available system memory or make any attempts to limit its memory usage. For example, it will never ‘refuse’ to honor an API call, as a result of it requiring a lot of memory.  HOOPS simply allocates (or will attempt to allocate) memory that it may require, based on the HOOPS/3DGS calls made by the developer. Any tracking and management of HOOPS memory usage must be handled in your application logic, and is facilitated by the function Show_Memory_Usage. This function returns the amount of memory that HOOPS has allocated, and how much memory is currently in-use.

Relinquishing Allocated Memory

If you find that there is a significant gap between 'allocated' and 'in-use', and you wish to reclaim some of the memory that HOOPS has allocated but is not currently using, you can consider calling Relinquish_Memory. This forces HOOPS to release unused memory back to the system, thereby defeating the benefits of HOOPS memory management system. This function should only be used in very specific situations, and also has major downsides on 32-bit systems. See its Reference Manual entry for more detailed Notes.

Raw Memory and Memory Debugging

If your HOOPS-based application is experiencing memory problems and are trying to determine where they are occurring, you can perform accurate HOOPS memory debugging by enabling the system option Define_System_Options_raw_memory "raw memory" via the Define_System_Options function. When this setting is turned on, HOOPS no longer uses its internal memory manager for dynamic memory allocation, but instead calls directly to the operating system for the allocation and freeing of memory. The direct calls to malloc and free allows a developer to easily track memory leaks using Valgrind, Visual Studio or any other memory debugging tool. Note that turning Define_System_Options_raw_memory "raw memory" on can significantly affect HOOPS/3DGS performance, and therefore this option should NOT be set for shipping versions of HOOPS-based application. Thus, by default, Define_System_Options_raw_memory "raw memory" is turned off.

 

7.5.2 Handling out-of-memory Conditions

This section describes how HOOPS behaves if it fails to allocated memory, and how an application should handle such situations.

While virtual memory is supported in all modern Operating Systems, an application can still effectively run out of memory on 32-bit systems well before the virtual memory is exhausted. This manifests itself by application code (HOOPS, etc...) attempting and failing to allocate large memory blocks, even though there may appear to be plenty of memory available in the Task Manager. This can occur as a result of 32-bit Operating System address fragmentation issues covered in Show_Memory_Usage documentation.  Also, while 64-bit systems may have a virtually unimited amount of memory, the performance of a memory-intensive application will typically degrade as more and more virtual memory is utilized, due to frequent hard disk memory paging activity. Therefore, even on 64-bit systems, it is beneficial to track and manage how much total memory your application is using.

  • When HOOPS attempts to allocate system memory and fails, it will:
    1. Report a WARNING error (Note: your app should have a HOOPS error-handler defined via Define_Error_Handler.):
      • category: HEC_MEMORY
      • specific: HES_OUT_OF_MEMORY
      • severity: 1 (‘warning’)  
    2. Automatically call Relinquish_Memory to try and free up some ‘allocated’ but ‘unused’ memory (as reported by Show_Memory_Usage)
    3. Make a 2nd attempt to allocate the desired memory
  • If the 2nd attempt at memory allocation succeeds, HOOPS continues on its way and the application behaves normally
  • If the 2nd attempt at memory allocation fails:
    1. HOOPS reports a FATAL error:
      • category: HEC_MEMORY
      • specific: HES_OUT_OF_MEMORY
      • severity: 3 (‘fatal error’) 
    2. An application CANNOT successfully return from any HOOPS fatal-error; the application will crash/hang if you try.  The best option at this point is for the application to gracefully exit (and perhaps display a dialog-box), and this requires the application to either longjmp (akin to a throw/exception in C++), or perform a ‘throw/exception’.   This is true of any fatal-errors in HOOPS, of which there are very few.  This HES_OUT_OF_MEMORY Fatal Error is the primary fatal error that could occur during typical HOOPS usage.

 

7.5.3 Memory Manager Overloading

If you wish to use your own memory manager, HOOPS provides functionality for more direct control of the internal memory usage via the malloc and free options in Define_System_Options. To use malloc and free, you must make Define_System_Options your first call to HOOPS and set these options at that time. The malloc option accepts a function pointer which will be used by HOOPS to request memory for new objects. The free option accepts a function pointer that HOOPS will use to release memory. Malloc and free must be set in conjunction with one another. Note that these options are persistent through a call to Reset_System.

If malloc and free options are set as well as raw memory, the malloc and free options will supercede the raw memory. Note that even when these memory options are used, HOOPS still uses the internal memory manager to control the allocation of small internal data structures.

 

7.5.4 Geometry Memory Optimizations

HOOPS/3DGS automatically performs a considerable amount of memory optimization internally for the storage and rendering of geometry. However, there a few special options and notes related to optimizing memory usage for faces.

7.5.4.1 Shell Facelists

HOOPS/3DGS retains the facelist passed into Insert_Shell by default. The number of bytes allocated for each shell facelist can be quite high. For example, given a shell with 1 million triangular faces, HOOPS/3DGS will use an extra 16MB of memory to perform the SSE-based software culling.

However, if the shell will not be edited, local shell attributes will not be edited after the first update, and the original facelist does not need to be accessed via Show_Shell, then the facelist need not be retained. Setting the conserve memory option to 'face list' in a call to Define_System_Options instructs HOOPS/3DGS to discard the facelist after the shell has been drawn for the first time.

  HC_Define_System_Options("conserve memory = face list");  

If the facelist has been discarded, then Show_Shell will return a facelist based on the interally-calculated tristrips, which means that each face will consist of a single triangle.

7.5.4.2 Software Culling Optimizations

HOOPS/3DGS tries to perform backplane culling using a technique called 'screen-plane facings' when display lists are turned off. This technique can improve rendering performance by up to 35%, but at the cost of additional memory usage for shell primitives. The number of bytes allocated for each shell's 'facings' can be up to twenty times the number of faces. For example, HOOPS/3dGS will use an additional 20 MB of memory to perform the SSE-based software culling for a shell with one million faces. This technique is only used if Intel x86 SSE extensions are available. If the extensions are not available, then culling will be performed as usual; specifically, it will be performed by the underlying 3D hardware if a 3D driver is being used, or via a regular software path if a 2D driver or software z-buffer is being used.

This functionality can be disabled by calling Define_System_Options and setting the conserve memory option to 'facings':

HC_Define_System_Options("conserve memory = facings"); 
Next

Previous

Index