Memory Allocation for Client Applications

The most important considerations for client applications are the following:

For most client applications (and interactive applications in particular), heap performance and serialization are not as great a factor when the application is run only on the client. They become more important when remote procedure calls (RPCs) are involved.

MAPI provides three functions that manage memory in a consistent way. MAPIAllocateBuffer, MAPIAllocateMore, and MAPIFreeBuffer enable client applications and service providers to exchange blocks of memory. MAPIAllocateBuffer is called initially to allocate memory for a buffer; MAPIAllocateMore can allocate another block of memory that is linked to the initial block.

When both client applications and service providers use these functions, whoever owns and is able to release a particular block of memory is no longer an issue. The service provider can simply allocate memory blocks and the client can later release them at will, independent of the service provider.

If the application has unusually high performance requirements, be aware that the MAPI allocation functions are serialized and do not offer control over the locality of allocations. Both of these factors can impair the performance of multithreaded applications. Use the Win32 memory allocator functions in this case.

Another thing to consider is that the very convenience of the MAPI allocators can affect performance. For example, MAPI providers always return memory allocated using MAPI allocators. So every time a call is made to IMAPIProp::GetProps, IMAPITable::QueryRows, or any MAPI functions, the memory is released and must be reallocated for the next call, so the client allocator itself is serialized if it is a MAPI allocator.

For general applications and most interactive ones, the CPU overhead incurred by the heap allocator is negligible. The difference in performance between the MAPI allocator and other allocators is also negligible. This includes many client applications and a few server applications that perform logging, reporting, link monitoring, and other tasks where flexibility and simplicity are more important than throughput.

Special consideration is required for 16-bit client memory allocation. Using the Windows 3.11 heap allocator may not be appropriate for your Microsoft Exchange Server client applications. The Win32 LocalAlloc function relies on a fixed-size heap in the application’s data segment and is too small for most usage. The Win32 GlobalAlloc function returns a new segment for each allocation, and only a limited number of segments are available, so it may not be a good choice for your application either. If your application must cover all platforms, MAPI allocators are often the best choice for local heap implementation. OLE allocators can also be used.

The C runtime function malloc has low overhead, but requires that memory is specifically freed. This function may be useful for applications if regular calls to the _heapmin function can be made. MAPI providers should never use malloc because they cannot predict when they will be called by the client. MAPI allocators support linked allocations, while OLE allocators do not. OLE supports resizing blocks, while MAPI does not. The 16-bit OLE allocator is not tolerant of a large number of allocated segments when the application itself has significant overhead.

For 32-bit clients, either HeapAlloc, VirtualAlloc, or a custom memory manager should be used, depending on whether there are special performance requirements for the memory manager.