From b9bd6f743843a53de1396c43d1e308e51d40c5c4 Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Mon, 17 Oct 2011 10:00:07 +0000 Subject: Reduce memory waste due to non-power-of-2 allocs This patch basically arranges for the allocation size of line_map buffers to be as close as possible to a power of two. This *significantly* decreases peak memory consumption as (macro) maps are numerous and stay live during all the compilation. The patch adds a new ggc_round_alloc_size interface to the ggc allocator. In each of the two main allocator implementations ('page' and 'zone') the function has been extracted from the main allocation function code and returns the actual size of the allocated memory region, thus giving a chance to the caller to maximize the amount of memory it actually uses from the allocated memory region. In the 'none' allocator implementation (that uses xmalloc) the ggc_round_alloc_size just returns the requested allocation size. Co-Authored-By: Dodji Seketeli From-SVN: r180086 --- libcpp/ChangeLog | 8 ++++++++ libcpp/include/line-map.h | 8 ++++++++ libcpp/line-map.c | 39 +++++++++++++++++++++++++++++++++------ 3 files changed, 49 insertions(+), 6 deletions(-) (limited to 'libcpp') diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog index fad0da6..3750720 100644 --- a/libcpp/ChangeLog +++ b/libcpp/ChangeLog @@ -1,6 +1,14 @@ 2011-10-15 Tom Tromey Dodji Seketeli + * include/line-map.h (struct line_maps::alloced_size_for_request): + New member. + * line-map.c (new_linemap): Use set->alloced_size_for_request to + get the actual allocated size of line maps. + +2011-10-15 Tom Tromey + Dodji Seketeli + * line-map.h (struct linemap_stats): Declare new struct. (linemap_get_statistics): Declare ... * line-map.c (linemap_get_statistics): ... new function. diff --git a/libcpp/include/line-map.h b/libcpp/include/line-map.h index 572e330..1e2a148 100644 --- a/libcpp/include/line-map.h +++ b/libcpp/include/line-map.h @@ -53,6 +53,10 @@ typedef unsigned int source_location; /* Memory allocation function typedef. Works like xrealloc. */ typedef void *(*line_map_realloc) (void *, size_t); +/* Memory allocator function that returns the actual allocated size, + for a given requested allocation. */ +typedef size_t (*line_map_round_alloc_size_func) (size_t); + /* An ordinary line map encodes physical source locations. Those physical source locations are called "spelling locations". @@ -281,6 +285,10 @@ struct GTY(()) line_maps { /* If non-null, the allocator to use when resizing 'maps'. If null, xrealloc is used. */ line_map_realloc reallocator; + + /* The allocators' function used to know the actual size it + allocated, for a certain allocation size requested. */ + line_map_round_alloc_size_func round_alloc_size; }; /* Returns the pointer to the memory region where information about diff --git a/libcpp/line-map.c b/libcpp/line-map.c index 9086b3e..87b8bfe 100644 --- a/libcpp/line-map.c +++ b/libcpp/line-map.c @@ -92,16 +92,43 @@ new_linemap (struct line_maps *set, if (LINEMAPS_USED (set, macro_map_p) == LINEMAPS_ALLOCATED (set, macro_map_p)) { /* We ran out of allocated line maps. Let's allocate more. */ + unsigned alloc_size; line_map_realloc reallocator = set->reallocator ? set->reallocator : xrealloc; + line_map_round_alloc_size_func round_alloc_size = + set->round_alloc_size; + + /* We are going to execute some dance to try to reduce the + overhead of the memory allocator, in case we are using the + ggc-page.c one. + + The actual size of memory we are going to get back from the + allocator is the smallest power of 2 that is greater than the + size we requested. So let's consider that size then. */ + + alloc_size = + (2 * LINEMAPS_ALLOCATED (set, macro_map_p) + 256) + * sizeof (struct line_map); + + /* Get the actual size of memory that is going to be allocated + by the allocator. */ + alloc_size = round_alloc_size (alloc_size); + + /* Now alloc_size contains the exact memory size we would get if + we have asked for the initial alloc_size amount of memory. + Let's get back to the number of macro map that amounts + to. */ LINEMAPS_ALLOCATED (set, macro_map_p) = - 2 * LINEMAPS_ALLOCATED (set, macro_map_p) + 256; - LINEMAPS_MAPS (set, macro_map_p) - = (struct line_map *) (*reallocator) (LINEMAPS_MAPS (set, macro_map_p), - LINEMAPS_ALLOCATED (set, - macro_map_p) - * sizeof (struct line_map)); + alloc_size / (sizeof (struct line_map)); + + /* And now let's really do the re-allocation. */ + LINEMAPS_MAPS (set, macro_map_p) = + (struct line_map *) (*reallocator) + (LINEMAPS_MAPS (set, macro_map_p), + (LINEMAPS_ALLOCATED (set, macro_map_p) + * sizeof (struct line_map))); + result = &LINEMAPS_MAPS (set, macro_map_p)[LINEMAPS_USED (set, macro_map_p)]; memset (result, 0, -- cgit v1.1