summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorljrittle <ljrittle@138bc75d-0d04-0410-961f-82ee72b054a4>2001-11-28 05:17:59 +0000
committerljrittle <ljrittle@138bc75d-0d04-0410-961f-82ee72b054a4>2001-11-28 05:17:59 +0000
commit709003369849b5c7d7bbd40b57410c5e42b0126c (patch)
tree6e607c30a729387545c0316b913f317c9857f048
parent24a656f21ce51518b02ae6a381d056196b8e9600 (diff)
downloadgcc-709003369849b5c7d7bbd40b57410c5e42b0126c.tar.gz
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@47398 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--libstdc++-v3/ChangeLog8
-rw-r--r--libstdc++-v3/include/bits/basic_string.tcc48
2 files changed, 56 insertions, 0 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index b86bf98c08a..70667905336 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -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.
diff --git a/libstdc++-v3/include/bits/basic_string.tcc b/libstdc++-v3/include/bits/basic_string.tcc
index d1dd1cb5d99..7a57f7df160 100644
--- a/libstdc++-v3/include/bits/basic_string.tcc
+++ b/libstdc++-v3/include/bits/basic_string.tcc
@@ -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);