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

Imperfect C++ Inventions: introduction

Recently, I've been asked by a couple of readers to enumerate the inventions and new definitions (as opposed to techniques, or already established technologies) introduced in Imperfect C++. Specifically, what are the (C++) programming components/techniques/technologies that I invented that are documented in the book.

To satisfy this request, I will make a series of posts covering the inventions and new definitions, including:
  • array_proxy
  • auto_buffer
  • dimensionof
  • Empty Derived Optimization (EDO)
  • explicit_cast
  • fast integer to string conversion
  • fast string concatenation
  • interface_cast
  • multi-dimensional array(s)
  • portable vtables
  • (C++) properties
  • ranges
  • shims
  • true typedefs
Each post will discuss technical details of the invention, any related art, the circumstances of its creation (usually necessity for something that the C++ language did not afford me), any technical limitations, and any well-known uses of it in projects or other software libraries.

Note 1: I'm only discussing inventions that are described in Imperfect C++. Things that I've later concocted are/will be discussed elsewhere. For example: the Type Tunnel and Handle::Ref+Wrapper patterns and the Principle of Intersecting Conformance will be discussed in Breaking Up The Monolith; C# Static Extension Methods will be discussed in Imperfect C#; and so on.

Note 2: I'm not claiming in every case that the invention is creditable only to me. Some were joint efforts (e.g. Ranges, with John Torjo); some are my taking an existing technique to new lengths and depths (e.g. Shims); some are my satisfying a known problem in a different way, or providing greater portability over existing forms (e.g. C++ properties). Other than those caveats, however, and the obvious "standing on the shoulders of giants" that is the business of all software designers, these are mine, and any similarity to other inventions, living or dead, is purely coincidental. ;-)

And, of course, there's something of an ulterior motive, in that the full descriptions and design decisions regarding each invention are to be found only in the book, which you may wish to consider getting hold of if you've not done so (particularly now that the reprint will shortly be available).

Reprint publication schedule

I've heard from my editor, and the next run of Imperfect C++ went to the printer on 20th November and should be bound on 11th December, so should be available towards the end of the month.

If you are still having issues with availability in the new year, please let me know and I'll contact the publisher for more information.