Library Memory Standard, 1st Draft

A proposal for high performance libraries


By Phil Frisbie, Jr.

Background

Many programmers use libraries to speed up the development time of applications. The standard C library is an example of a library used by most C applications. Other third party libraries provide enhanced functions for such things as graphics, sound, networking, and input. Many libraries also offer cross platform compatibility so that porting applications is easier.

Libraries vary in quality and functionality, but many have one flaw in common, and that is poor memory integration with the application. These libraries need to allocate temporary memory, and they simply use the C run-time (CRT) malloc() and free() functions. While this is fine for many applications, it can cause problems with high performance applications that use a custom memory manager (CMM).

High performance applications, such as games, can often receive a large boost in performance by using a CMM. The CRT memory functions are designed to be general purpose, but the CMM can be tuned to the type of memory allocations common in the application. The CMM can also include additional run-time debugging to help quickly track down memory access errors. When an application using a CMM is linked to a library that uses CRT memory functions, it will not perform it's best, it can make debugging harder, and it could cause memory leaks if memory is allocated by the CRT and the application tries to free it using the CMM.

There is another problem unique to Windows when the library is supplied as a DLL. There are two CRT DLLs that the application or library might dynamically link to (single and multithreaded), or it may even be statically linked to one of those CRTs. So, there are 16 possible combinations of application and library run times! The following proposal also eliminates this problem.

The proposal

The Library Memory Standard is composed of three parts:

The API interface between the application and the library.
The optional CMM for use inside the library (the library internal CMM, or LCMM).
Documentation listing the library functions that allocate and free memory.

The API interface provides a way to allow the library to be made aware of the application's CMM. The API is two functions with three type defines, as prototyped below. (Note: 'xyz' is the prefix used by the example library, and will be substituted by the library prefix in a real library)

typedef void *(*CMMmalloc)(size_t size); /* CMM malloc implementation */
typedef void (*CMMfree)(void *memblock);  /* CMM free implementation */
typedef void *(*CMMrealloc)(void *memblock, size_t size);  /* CMM realloc
                                              implementation, optional */

void xyzSetCMM(CMMmalloc m, CMMfree f, CMMrealloc r);
void xyzHint(enum hint);

The first function, xyzSetCMM(), is used to set, or hook, the library's memory allocation functions. This should be called before any other library function so that all memory allocations will use the application's CMM. If the application's CMM does not implement the equivalent to realloc(), then pass NULL so that the library will use it's own realloc() function. The three function prototypes, CMMmalloc, CMMfree, and CMMrealloc are fully interchangeable with the ANSI C functions malloc, free, and realloc.

The second function, xyzHint(), is used to control the optional LCMM, and as such it is also optional. If it is provided, the hints will include at least the following: CONSERVE_MEMORY, and USE_CMM. CONSERVE_MEMORY will disable the use of the LCMM, and USE_CMM will enable it. USE_CMM can be used with or without xyzSetCMM. If the application does not have a CMM, then the LCMM will boost the performance of the library, but even if the application does have a CMM, it may not work well for the library. The LCMM will cause more memory to be allocated to the library, so performance testing should be done to see if the performance boost is worth the extra memory usage.

The library code needed to implement the LCMM is beyond the scope of this proposal. If it is provided, it should be highly tuned to the needs of the library.

The last item, the documentation listing the library functions that allocate and free memory, is the easiest part, but still very important to the application programmer. This documentation should at least list which functions allocate and/or free memory. The approximate amount of memory allocated could also be useful in cases where the library will be using the application's CMM. The application's CMM could then be tuned for the common allocation sizes needed by the library.

Conclusion

These guidelines are designed to make libraries not only easier to use, but faster and better documented. They are not intentionally biased towards any operating system, compiler, or library type. Although my examples are specific to C applications and libraries, these guidelines can be adapted to any language that supports allocating and freeing memory dynamically.

Comments and suggestions are welcome, and these guidelines will be updated accordingly. Send all comments to Phil Frisbie, Jr..


Page last modified: 10 August 2005
© 1998-2006 Hawk Software