basic_string.tcc (basic_string::_Rep::_S_create): Enforce allocation size blocking policy to reduce fragmentation and enhance...

2001-11-27  Loren J. Rittle  <ljrittle@acm.org>
            Paolo Carlini  <pcarlini@unitus.it>

        * include/bits/basic_string.tcc (basic_string::_Rep::_S_create):
        Enforce allocation size blocking policy to reduce
        fragmentation and enhance performance with common malloc
        implementations.

Co-Authored-By: Paolo Carlini <pcarlini@unitus.it>

From-SVN: r47398
This commit is contained in:
Loren J. Rittle 2001-11-28 05:17:59 +00:00 committed by Loren J. Rittle
parent 86ade44cb2
commit 2883d58bf5
2 changed files with 56 additions and 0 deletions

View File

@ -1,3 +1,11 @@
2001-11-27 Loren J. Rittle <ljrittle@acm.org>
Paolo Carlini <pcarlini@unitus.it>
* include/bits/basic_string.tcc (basic_string::_Rep::_S_create):
Enforce allocation size blocking policy to reduce
fragmentation and enhance performance with common malloc
implementations.
2001-11-27 Benjamin Kosnik <bkoz@redhat.com>
Numeric facets cleanup.

View File

@ -374,6 +374,54 @@ namespace std
// terminating null char_type() element, plus enough for the
// _Rep data structure. Whew. Seemingly so needy, yet so elemental.
size_t __size = (__capacity + 1) * sizeof(_CharT) + sizeof(_Rep);
// The standard places no restriction on allocating more memory
// than is strictly needed within this layer at the moment or as
// requested by an explicit application call to reserve(). Many
// malloc implementations perform quite poorly when an
// application attempts to allocate memory in a stepwise fashion
// growing each allocation size by only 1 char. Additionally,
// it makes little sense to allocate less linear memory than the
// natural blocking size of the malloc implementation.
// Unfortunately, we would need a somewhat low-level calculation
// with tuned parameters to get this perfect for any particular
// malloc implementation. Fortunately, generalizations about
// common features seen among implementations seems to suffice.
// This algorithm does not replace the need for an exponential
// growth shaper to meet library specification. Note: THIS IS
// NOT THE CORRECT LOCATION FOR AN EXPONENTIAL GROWTH SHAPER
// (since this code affect initial allocation as well as
// reallocation).
// __pagesize need not match the actual VM page size for good
// results in practice, thus we pick a common value on the low
// side. __malloc_header_size is an estimate of the amount of
// overhead per memory allocation (in practice seen N * sizeof
// (void*) where N is 0, 2 or 4). According to folklore,
// picking this value on the high side is better than
// low-balling it (especially when this algorithm is used with
// malloc implementations that allocate memory blocks rounded up
// to a size which is a power of 2).
const size_t __pagesize = 4096; // must be 2^i * __subpagesize
const size_t __subpagesize = 128; // should be >> __malloc_header_size
const size_t __malloc_header_size = 4 * sizeof (void*);
if ((__size + __malloc_header_size) > __pagesize)
{
size_t __extra =
(__pagesize - ((__size + __malloc_header_size) % __pagesize))
% __pagesize;
__capacity += __extra / sizeof(_CharT);
__size = (__capacity + 1) * sizeof(_CharT) + sizeof(_Rep);
}
else if (__size > __subpagesize)
{
size_t __extra =
(__subpagesize - ((__size + __malloc_header_size) % __subpagesize))
% __subpagesize;
__capacity += __extra / sizeof(_CharT);
__size = (__capacity + 1) * sizeof(_CharT) + sizeof(_Rep);
}
// NB: Might throw, but no worries about a leak, mate: _Rep()
// does not throw.
void* __place = _Raw_bytes_alloc(__alloc).allocate(__size);