Friday, December 4, 2009

Imperfect C++ Inventions #1: auto_buffer

Characterisation

auto_buffer is a C++ class template.

Purpose

It's purpose is to avoid memory allocation costs in cases where the sizes of most, but not all, allocations for a given operation are known to occur below a certain threshold. It is intended to be used as a variable in automatic scope (i.e. a stack variable). This is very common in cases such as allocating space for a file-system path, where most fall within, say, 100 characters, but rare cases may extend to several thousand characters: using a stack buffer of 100 would lead to overruns, using a stack buffer of 10,000 would, even if above the maximum value, lead to undesirable stack-related performance effects.

It is implemented in terms of a standard allocator-conformant type, determined via the specialisation of the auto_buffer class template, defaulted to a specialisation of std::allocator. By design, it can be specialized only by POD types, since one of the . As noted in section 16.2.1 of Extended STL, volume 1, despite, for convenience, providing many methods found on standard containers, auto_buffer is not a container, and should ever be mistaken for such.

As extensive performance studies (and a lot of real-world use) have demonstrated, auto_buffer is effectively a way of having (almost) all the performance of stack-based memory allocation while having the flexibility of heap-based memory allocation. Furthermore, it is portable and has no drawbacks as regards its intended purpose; all other options, such as alloca() and Variable-Length Arrays, have unacceptable behaviour and/or portability and/or language-specificity, as described in detail in chapter 32 of Imperfect C++.


History

auto_buffer had a very prosaic start in life. Long ago, in a programming fashion far, far away, I was implementing a suite of utility functions providing a multibyte string conversion layer over an API that was implemented in terms of wide strings. The first implementation used the heap to allocate a block of memory in which to write the converted form, before passing on to the underlying API. Understandably, this rankled, particularly when most of the converted strings fell well within a buffer size that one might comfortably use on the stack at the time (early 1990s).

The second implementation of these utilities consequently declared a local (stack) buffer, which was used if it could accommodate the given requirement, otherwise the heap was used as before. Later, once enough compilers caught up with the requirements of the type, these implementations were replaced by LocalBuffer, the Synesis Software class template that later evolved into STLSoft's auto_buffer.

Implementations

Implementations of auto_buffer are found for STLSoft and Boost:

Dependencies

It has dependencies only on standard facilities.

Uses

Within STLSoft, auto_buffer is used within many components, including ones for character encoding and conversion, process enumeration, Windows registry, ACE communications component adaptors, formatting functions, file-system processing, to name but a few.

In other open-source libraries it is used to enhance performance at the function-scale, particularly in the high-performance formatting and diagnostic logging libraries, FastFormat and Pantheios.

Being a low-level component - in particular, being (by design) only specializable for POD types - it tends not to be used too often in application code. Nonetheless, in several commercial applications in recent years, I have found a need for the component, to assist in safely optimising performance bottlenecks where the majority of memory allocations fall within a known bound.

Further Reading

No comments:

Post a Comment