diff options
author | dodji <dodji@138bc75d-0d04-0410-961f-82ee72b054a4> | 2011-10-17 10:00:07 +0000 |
---|---|---|
committer | dodji <dodji@138bc75d-0d04-0410-961f-82ee72b054a4> | 2011-10-17 10:00:07 +0000 |
commit | 1ae3520e0d4d2a5693961919636474de0a4faef6 (patch) | |
tree | 0b0e309c095d0459230339edc0343cafe8f0c4c8 /gcc | |
parent | e77b8253aa187580c9e185461ed28c207e693126 (diff) | |
download | gcc-1ae3520e0d4d2a5693961919636474de0a4faef6.tar.gz |
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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@180086 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 16 | ||||
-rw-r--r-- | gcc/ggc-none.c | 9 | ||||
-rw-r--r-- | gcc/ggc-page.c | 53 | ||||
-rw-r--r-- | gcc/ggc-zone.c | 27 | ||||
-rw-r--r-- | gcc/ggc.h | 2 | ||||
-rw-r--r-- | gcc/toplev.c | 1 |
6 files changed, 89 insertions, 19 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 81caf547177..557916c82bc 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,6 +1,22 @@ 2011-10-15 Tom Tromey <tromey@redhat.com> Dodji Seketeli <dodji@redhat.com> + * ggc.h (ggc_round_alloc_size): Declare new public entry point. + * ggc-none.c (ggc_round_alloc_size): New public stub function. + * ggc-page.c (ggc_alloced_size_order_for_request): New static + function. Factorized from ggc_internal_alloc_stat. + (ggc_round_alloc_size): New public function. Uses + ggc_alloced_size_order_for_request. + (ggc_internal_alloc_stat): Use ggc_alloced_size_order_for_request. + * ggc-zone.c (ggc_round_alloc_size): New public function extracted + from ggc_internal_alloc_zone_stat. + (ggc_internal_alloc_zone_stat): Use ggc_round_alloc_size. + * toplev.c (general_init): Initialize + line_table->alloced_size_for_request. + +2011-10-15 Tom Tromey <tromey@redhat.com> + Dodji Seketeli <dodji@redhat.com> + * input.c (ONE_K, ONE_M, SCALE, STAT_LABEL, FORMAT_AMOUNT): New macros. (num_expanded_macros_counter, num_macro_tokens_counter): Declare diff --git a/gcc/ggc-none.c b/gcc/ggc-none.c index 97d25b9b653..e57d61787df 100644 --- a/gcc/ggc-none.c +++ b/gcc/ggc-none.c @@ -39,6 +39,15 @@ ggc_alloc_typed_stat (enum gt_types_enum ARG_UNUSED (gte), size_t size return xmalloc (size); } +/* For a given size of memory requested for allocation, return the + actual size that is going to be allocated. */ + +size_t +ggc_round_alloc_size (size_t requested_size) +{ + return requested_size; +} + void * ggc_internal_alloc_stat (size_t size MEM_STAT_DECL) { diff --git a/gcc/ggc-page.c b/gcc/ggc-page.c index a218f7696d7..beee851dd7f 100644 --- a/gcc/ggc-page.c +++ b/gcc/ggc-page.c @@ -1054,6 +1054,47 @@ static unsigned char size_lookup[NUM_SIZE_LOOKUP] = 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 }; +/* For a given size of memory requested for allocation, return the + actual size that is going to be allocated, as well as the size + order. */ + +static void +ggc_round_alloc_size_1 (size_t requested_size, + size_t *size_order, + size_t *alloced_size) +{ + size_t order, object_size; + + if (requested_size < NUM_SIZE_LOOKUP) + { + order = size_lookup[requested_size]; + object_size = OBJECT_SIZE (order); + } + else + { + order = 10; + while (requested_size > (object_size = OBJECT_SIZE (order))) + order++; + } + + if (size_order) + *size_order = order; + if (alloced_size) + *alloced_size = object_size; +} + +/* For a given size of memory requested for allocation, return the + actual size that is going to be allocated. */ + +size_t +ggc_round_alloc_size (size_t requested_size) +{ + size_t size = 0; + + ggc_round_alloc_size_1 (requested_size, NULL, &size); + return size; +} + /* Typed allocation function. Does nothing special in this collector. */ void * @@ -1072,17 +1113,7 @@ ggc_internal_alloc_stat (size_t size MEM_STAT_DECL) struct page_entry *entry; void *result; - if (size < NUM_SIZE_LOOKUP) - { - order = size_lookup[size]; - object_size = OBJECT_SIZE (order); - } - else - { - order = 10; - while (size > (object_size = OBJECT_SIZE (order))) - order++; - } + ggc_round_alloc_size_1 (size, &order, &object_size); /* If there are non-full pages for this size allocation, they are at the head of the list. */ diff --git a/gcc/ggc-zone.c b/gcc/ggc-zone.c index d0c1d79f53d..79c8c032966 100644 --- a/gcc/ggc-zone.c +++ b/gcc/ggc-zone.c @@ -1073,6 +1073,24 @@ free_chunk (char *ptr, size_t size, struct alloc_zone *zone) fprintf (G.debug_file, "Deallocating object, chunk=%p\n", (void *)chunk); } +/* For a given size of memory requested for allocation, return the + actual size that is going to be allocated. */ + +size_t +ggc_round_alloc_size (size_t requested_size) +{ + size_t size; + + /* Make sure that zero-sized allocations get a unique and freeable + pointer. */ + if (requested_size == 0) + size = MAX_ALIGNMENT; + else + size = (requested_size + MAX_ALIGNMENT - 1) & -MAX_ALIGNMENT; + + return size; +} + /* Allocate a chunk of memory of at least ORIG_SIZE bytes, in ZONE. */ void * @@ -1084,14 +1102,7 @@ ggc_internal_alloc_zone_stat (size_t orig_size, struct alloc_zone *zone struct small_page_entry *entry; struct alloc_chunk *chunk, **pp; void *result; - size_t size = orig_size; - - /* Make sure that zero-sized allocations get a unique and freeable - pointer. */ - if (size == 0) - size = MAX_ALIGNMENT; - else - size = (size + MAX_ALIGNMENT - 1) & -MAX_ALIGNMENT; + size_t size = ggc_alloced_size_for_request (orig_size); /* Try to allocate the object from several different sources. Each of these cases is responsible for setting RESULT and SIZE to diff --git a/gcc/ggc.h b/gcc/ggc.h index 30eca66c302..704237cc045 100644 --- a/gcc/ggc.h +++ b/gcc/ggc.h @@ -145,6 +145,8 @@ extern void gt_pch_save (FILE *f); /* The internal primitive. */ extern void *ggc_internal_alloc_stat (size_t MEM_STAT_DECL); +extern size_t ggc_round_alloc_size (size_t requested_size); + #define ggc_internal_alloc(s) ggc_internal_alloc_stat (s MEM_STAT_INFO) /* Allocate an object of the specified type and size. */ diff --git a/gcc/toplev.c b/gcc/toplev.c index f508196b3eb..86eed5d63a8 100644 --- a/gcc/toplev.c +++ b/gcc/toplev.c @@ -1216,6 +1216,7 @@ general_init (const char *argv0) line_table = ggc_alloc_line_maps (); linemap_init (line_table); line_table->reallocator = realloc_for_line_map; + line_table->round_alloc_size = ggc_round_alloc_size; init_ttree (); /* Initialize register usage now so switches may override. */ |