ggc.h (struct ggc_statistics): New type.

* ggc.h (struct ggc_statistics): New type.
	(ggc_get_size): New function.
	(ggc_print_statistics): Likewise.
	* ggc-common.c (ggc_stats): New variable.
	(ggc_mark_rtx_children): Keep statistics.
	(ggc_mark_tree_children): Likewise.
	(ggc_print_statistics): New function.
	* ggc-page.c (struct globals): Add bytes_mapped field.
	(alloc_anon): Update it.
	(release_pages): Likewise.
	(ggc_get_size): New function.
	(ggc_page_print_statistics): New function.
	* ggc-simple.c (ggc_get_size): New function.

From-SVN: r30251
This commit is contained in:
Mark Mitchell 1999-10-29 04:17:33 +00:00 committed by Mark Mitchell
parent 13e8cf822f
commit 3277221c45
5 changed files with 217 additions and 3 deletions

View File

@ -1,3 +1,19 @@
Thu Oct 28 21:16:35 1999 Mark Mitchell <mark@codesourcery.com>
* ggc.h (struct ggc_statistics): New type.
(ggc_get_size): New function.
(ggc_print_statistics): Likewise.
* ggc-common.c (ggc_stats): New variable.
(ggc_mark_rtx_children): Keep statistics.
(ggc_mark_tree_children): Likewise.
(ggc_print_statistics): New function.
* ggc-page.c (struct globals): Add bytes_mapped field.
(alloc_anon): Update it.
(release_pages): Likewise.
(ggc_get_size): New function.
(ggc_page_print_statistics): New function.
* ggc-simple.c (ggc_get_size): New function.
Fri Oct 29 06:32:44 1999 Geoffrey Keating <geoffk@cygnus.com>
* flow.c (propagate_block): When the last reference to a label

View File

@ -30,6 +30,9 @@
#include "varray.h"
#include "ggc.h"
/* Statistics about the allocation. */
static ggc_statistics *ggc_stats;
static void ggc_mark_rtx_ptr PARAMS ((void *));
static void ggc_mark_tree_ptr PARAMS ((void *));
static void ggc_mark_tree_varray_ptr PARAMS ((void *));
@ -211,10 +214,18 @@ ggc_mark_rtx_children (r)
{
const char *fmt;
int i;
enum rtx_code code = GET_CODE (r);
/* Collect statistics, if appropriate. */
if (ggc_stats)
{
++ggc_stats->num_rtxs[(int) code];
ggc_stats->size_rtxs[(int) code] += ggc_get_size (r);
}
/* ??? If (some of) these are really pass-dependant info, do we have
any right poking our noses in? */
switch (GET_CODE (r))
switch (code)
{
case JUMP_INSN:
ggc_mark_rtx (JUMP_LABEL (r));
@ -289,12 +300,21 @@ void
ggc_mark_tree_children (t)
tree t;
{
enum tree_code code = TREE_CODE (t);
/* Collect statistics, if appropriate. */
if (ggc_stats)
{
++ggc_stats->num_trees[(int) code];
ggc_stats->size_trees[(int) code] += ggc_get_size (t);
}
/* Bits from common. */
ggc_mark_tree (TREE_TYPE (t));
ggc_mark_tree (TREE_CHAIN (t));
/* Some nodes require special handling. */
switch (TREE_CODE (t))
switch (code)
{
case TREE_LIST:
ggc_mark_tree (TREE_PURPOSE (t));
@ -349,7 +369,7 @@ ggc_mark_tree_children (t)
}
/* But in general we can handle them by class. */
switch (TREE_CODE_CLASS (TREE_CODE (t)))
switch (TREE_CODE_CLASS (code))
{
case 'd': /* A decl node. */
ggc_mark_string (DECL_SOURCE_FILE (t));
@ -469,3 +489,74 @@ ggc_alloc_string (contents, length)
return string;
}
/* Print statistics that are independent of the collector in use. */
void
ggc_print_statistics (stream, stats)
FILE *stream;
ggc_statistics *stats;
{
int code;
/* Set the pointer so that during collection we will actually gather
the statistics. */
ggc_stats = stats;
/* Then do one collection to fill in the statistics. */
ggc_collect ();
/* Total the statistics. */
for (code = 0; code < MAX_TREE_CODES; ++code)
{
stats->total_num_trees += stats->num_trees[code];
stats->total_size_trees += stats->size_trees[code];
}
for (code = 0; code < NUM_RTX_CODE; ++code)
{
stats->total_num_rtxs += stats->num_rtxs[code];
stats->total_size_rtxs += stats->size_rtxs[code];
}
/* Print the statistics for trees. */
fprintf (stream, "%-22s%-16s%-16s%-7s\n", "Code",
"Number", "Bytes", "% Total");
for (code = 0; code < MAX_TREE_CODES; ++code)
if (ggc_stats->num_trees[code])
{
fprintf (stream, "%s%*s%-15u %-15u %7.3f\n",
tree_code_name[code],
22 - strlen (tree_code_name[code]), "",
ggc_stats->num_trees[code],
ggc_stats->size_trees[code],
(100 * ((double) ggc_stats->size_trees[code])
/ ggc_stats->total_size_trees));
}
fprintf (stream,
"%-22s%-15u %-15u\n", "Total",
ggc_stats->total_num_trees,
ggc_stats->total_size_trees);
/* Print the statistics for RTL. */
fprintf (stream, "\n%-22s%-16s%-16s%-7s\n", "Code",
"Number", "Bytes", "% Total");
for (code = 0; code < NUM_RTX_CODE; ++code)
if (ggc_stats->num_rtxs[code])
{
fprintf (stream, "%s%*s%-15u %-15u %7.3f\n",
rtx_name[code],
22 - strlen (rtx_name[code]), "",
ggc_stats->num_rtxs[code],
ggc_stats->size_rtxs[code],
(100 * ((double) ggc_stats->size_rtxs[code])
/ ggc_stats->total_size_rtxs));
}
fprintf (stream,
"%-22s%-15u %-15u\n", "Total",
ggc_stats->total_num_rtxs,
ggc_stats->total_size_rtxs);
/* Don't gather statistics any more. */
ggc_stats = NULL;
}

View File

@ -226,6 +226,9 @@ static struct globals
/* Bytes currently allocated at the end of the last collection. */
size_t allocated_last_gc;
/* Total amount of memory mapped. */
size_t bytes_mapped;
/* The current depth in the context stack. */
unsigned char context_depth;
@ -444,6 +447,9 @@ alloc_anon (pref, size)
#endif /* HAVE_VALLOC */
#endif /* HAVE_MMAP */
/* Remember that we allocated this memory. */
G.bytes_mapped += size;
return page;
}
@ -565,6 +571,7 @@ release_pages ()
else
{
munmap (start, len);
G.bytes_mapped -= len;
start = p->page;
len = p->bytes;
}
@ -573,6 +580,7 @@ release_pages ()
}
munmap (start, len);
G.bytes_mapped -= len;
#else
#ifdef HAVE_VALLOC
page_entry *p, *next;
@ -581,6 +589,7 @@ release_pages ()
{
next = p->next;
free (p->page);
G.bytes_mapped -= p->bytes;
free (p);
}
#endif /* HAVE_VALLOC */
@ -778,6 +787,14 @@ ggc_mark_if_gcable (p)
if (p && ggc_allocated_p (p))
ggc_set_mark (p);
}
size_t
ggc_get_size (p)
void *p;
{
page_entry *pe = lookup_page_table_entry (p);
return 1 << pe->order;
}
/* Initialize the ggc-mmap allocator. */
void
@ -1088,3 +1105,51 @@ ggc_collect ()
(unsigned long) G.allocated / 1024, time * 1e-6);
}
}
/* Print allocation statistics. */
void
ggc_page_print_statistics ()
{
struct ggc_statistics stats;
int i;
/* Clear the statistics. */
bzero (&stats, sizeof (stats));
/* Make sure collection will really occur. */
G.allocated_last_gc = 0;
/* Collect and print the statistics common across collectors. */
ggc_print_statistics (stderr, &stats);
/* Collect some information about the various sizes of
allocation. */
fprintf (stderr, "\n%-4s%-16s%-16s\n", "Log", "Allocated", "Used");
for (i = 0; i < HOST_BITS_PER_PTR; ++i)
{
page_entry *p;
size_t allocated;
size_t in_use;
/* Skip empty entries. */
if (!G.pages[i])
continue;
allocated = in_use = 0;
/* Figure out the total number of bytes allocated for objects of
this size, and how many of them are actually in use. */
for (p = G.pages[i]; p; p = p->next)
{
allocated += p->bytes;
in_use +=
(OBJECTS_PER_PAGE (i) - p->num_free_objects) * (1 << i);
}
fprintf (stderr, "%-3d %-15u %-15u\n", i, allocated, in_use);
}
/* Print out some global information. */
fprintf (stderr, "\nTotal bytes marked: %u\n", G.allocated);
fprintf (stderr, "Total bytes mapped: %u\n", G.bytes_mapped);
}

View File

@ -253,6 +253,15 @@ ggc_mark_if_gcable (p)
G.objects += 1;
}
size_t
ggc_get_size (p)
void *p;
{
struct ggc_mem *x
= (struct ggc_mem *) ((char *)p - offsetof (struct ggc_mem, u));
return x->size;
}
static void
clear_marks (x)
struct ggc_mem *x;

View File

@ -165,3 +165,36 @@ void mark_expr_status PROTO ((struct expr_status *));
void mark_stmt_status PROTO ((struct stmt_status *));
void mark_varasm_status PROTO ((struct varasm_status *));
void mark_optab PROTO ((void *));
/* Statistics. */
/* This structure contains the statistics common to all collectors.
Particular collectors can extend this structure. */
typedef struct ggc_statistics
{
/* The Ith element is the number of nodes allocated with code I. */
unsigned num_trees[256];
/* The Ith element is the number of bytes allocated by nodes with
code I. */
size_t size_trees[256];
/* The Ith element is the number of nodes allocated with code I. */
unsigned num_rtxs[256];
/* The Ith element is the number of bytes allocated by nodes with
code I. */
size_t size_rtxs[256];
/* The total number of tree nodes allocated. */
unsigned total_num_trees;
/* The total size of the tree nodes allocated. */
size_t total_size_trees;
/* The total number of RTL nodes allocated. */
unsigned total_num_rtxs;
/* The total size of the RTL nodes allocated. */
size_t total_size_rtxs;
} ggc_statistics;
/* Return the number of bytes allocated at the indicated address. */
size_t ggc_get_size PROTO ((void *));
/* Used by the various collectors to gather and print statistics that
do not depend on the collector in use. */
void ggc_print_statistics PROTO ((FILE *, ggc_statistics *));