* config/tc-xtensa.c (xtensa_mark_literal_pool_location): Remove
[deliverable/binutils-gdb.git] / gdb / bcache.c
CommitLineData
c906108c 1/* Implement a cached obstack.
c2d11a7d
JM
2 Written by Fred Fish <fnf@cygnus.com>
3 Rewritten by Jim Blandy <jimb@cygnus.com>
2c7ef074
AC
4
5 Copyright 1999, 2000, 2002 Free Software Foundation, Inc.
c906108c 6
c5aa993b 7 This file is part of GDB.
c906108c 8
c5aa993b
JM
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
c906108c 13
c5aa993b
JM
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
c906108c 18
c5aa993b
JM
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place - Suite 330,
22 Boston, MA 02111-1307, USA. */
c906108c
SS
23
24#include "defs.h"
04ea0df1 25#include "gdb_obstack.h"
c906108c
SS
26#include "bcache.h"
27#include "gdb_string.h" /* For memcpy declaration */
28
2c7ef074
AC
29#include <stddef.h>
30#include <stdlib.h>
31
af5f3db6
AC
32/* The type used to hold a single bcache string. The user data is
33 stored in d.data. Since it can be any type, it needs to have the
34 same alignment as the most strict alignment of any type on the host
35 machine. I don't know of any really correct way to do this in
36 stock ANSI C, so just do it the same way obstack.h does. */
37
38struct bstring
39{
40 struct bstring *next;
41 size_t length;
42
43 union
44 {
45 char data[1];
46 double dummy;
47 }
48 d;
49};
50
51
52/* The structure for a bcache itself. The bcache is initialized, in
53 bcache_xmalloc(), by filling it with zeros and then setting the
54 corresponding obstack's malloc() and free() methods. */
55
56struct bcache
57{
58 /* All the bstrings are allocated here. */
59 struct obstack cache;
60
61 /* How many hash buckets we're using. */
62 unsigned int num_buckets;
63
64 /* Hash buckets. This table is allocated using malloc, so when we
65 grow the table we can return the old table to the system. */
66 struct bstring **bucket;
67
68 /* Statistics. */
69 unsigned long unique_count; /* number of unique strings */
70 long total_count; /* total number of strings cached, including dups */
71 long unique_size; /* size of unique strings, in bytes */
72 long total_size; /* total number of bytes cached, including dups */
73 long structure_size; /* total size of bcache, including infrastructure */
74};
75
357e46e7
DB
76/* The old hash function was stolen from SDBM. This is what DB 3.0 uses now,
77 * and is better than the old one.
78 */
c2d11a7d 79\f
c2d11a7d 80unsigned long
d85a5daf 81hash(const void *addr, int length)
c2d11a7d 82{
357e46e7
DB
83 const unsigned char *k, *e;
84 unsigned long h;
85
86 k = (const unsigned char *)addr;
87 e = k+length;
88 for (h=0; k< e;++k)
89 {
90 h *=16777619;
91 h ^= *k;
92 }
93 return (h);
c906108c 94}
c2d11a7d
JM
95\f
96/* Growing the bcache's hash table. */
97
98/* If the average chain length grows beyond this, then we want to
99 resize our hash table. */
100#define CHAIN_LENGTH_THRESHOLD (5)
101
102static void
103expand_hash_table (struct bcache *bcache)
c906108c 104{
c2d11a7d
JM
105 /* A table of good hash table sizes. Whenever we grow, we pick the
106 next larger size from this table. sizes[i] is close to 1 << (i+10),
107 so we roughly double the table size each time. After we fall off
108 the end of this table, we just double. Don't laugh --- there have
109 been executables sighted with a gigabyte of debug info. */
110 static unsigned long sizes[] = {
111 1021, 2053, 4099, 8191, 16381, 32771,
112 65537, 131071, 262144, 524287, 1048573, 2097143,
113 4194301, 8388617, 16777213, 33554467, 67108859, 134217757,
114 268435459, 536870923, 1073741827, 2147483659UL
115 };
745b8ca0 116 unsigned int new_num_buckets;
c2d11a7d 117 struct bstring **new_buckets;
745b8ca0 118 unsigned int i;
c2d11a7d
JM
119
120 /* Find the next size. */
745b8ca0 121 new_num_buckets = bcache->num_buckets * 2;
c2d11a7d
JM
122 for (i = 0; i < (sizeof (sizes) / sizeof (sizes[0])); i++)
123 if (sizes[i] > bcache->num_buckets)
124 {
125 new_num_buckets = sizes[i];
126 break;
127 }
c2d11a7d
JM
128
129 /* Allocate the new table. */
130 {
131 size_t new_size = new_num_buckets * sizeof (new_buckets[0]);
132 new_buckets = (struct bstring **) xmalloc (new_size);
133 memset (new_buckets, 0, new_size);
134
135 bcache->structure_size -= (bcache->num_buckets
136 * sizeof (bcache->bucket[0]));
137 bcache->structure_size += new_size;
138 }
c906108c 139
c2d11a7d
JM
140 /* Rehash all existing strings. */
141 for (i = 0; i < bcache->num_buckets; i++)
c906108c 142 {
c2d11a7d
JM
143 struct bstring *s, *next;
144
145 for (s = bcache->bucket[i]; s; s = next)
c906108c 146 {
c2d11a7d
JM
147 struct bstring **new_bucket;
148 next = s->next;
149
150 new_bucket = &new_buckets[(hash (&s->d.data, s->length)
151 % new_num_buckets)];
152 s->next = *new_bucket;
153 *new_bucket = s;
c906108c
SS
154 }
155 }
c2d11a7d
JM
156
157 /* Plug in the new table. */
158 if (bcache->bucket)
b8c9b27d 159 xfree (bcache->bucket);
c2d11a7d
JM
160 bcache->bucket = new_buckets;
161 bcache->num_buckets = new_num_buckets;
c906108c
SS
162}
163
c2d11a7d
JM
164\f
165/* Looking up things in the bcache. */
166
167/* The number of bytes needed to allocate a struct bstring whose data
168 is N bytes long. */
169#define BSTRING_SIZE(n) (offsetof (struct bstring, d.data) + (n))
170
171/* Find a copy of the LENGTH bytes at ADDR in BCACHE. If BCACHE has
172 never seen those bytes before, add a copy of them to BCACHE. In
173 either case, return a pointer to BCACHE's copy of that string. */
c906108c 174void *
d85a5daf 175bcache (const void *addr, int length, struct bcache *bcache)
c906108c 176{
c2d11a7d
JM
177 int hash_index;
178 struct bstring *s;
c906108c 179
c2d11a7d
JM
180 /* If our average chain length is too high, expand the hash table. */
181 if (bcache->unique_count >= bcache->num_buckets * CHAIN_LENGTH_THRESHOLD)
182 expand_hash_table (bcache);
183
184 bcache->total_count++;
185 bcache->total_size += length;
186
187 hash_index = hash (addr, length) % bcache->num_buckets;
188
189 /* Search the hash bucket for a string identical to the caller's. */
190 for (s = bcache->bucket[hash_index]; s; s = s->next)
191 if (s->length == length
192 && ! memcmp (&s->d.data, addr, length))
193 return &s->d.data;
194
195 /* The user's string isn't in the list. Insert it after *ps. */
196 {
197 struct bstring *new
198 = obstack_alloc (&bcache->cache, BSTRING_SIZE (length));
199 memcpy (&new->d.data, addr, length);
200 new->length = length;
201 new->next = bcache->bucket[hash_index];
202 bcache->bucket[hash_index] = new;
203
204 bcache->unique_count++;
205 bcache->unique_size += length;
206 bcache->structure_size += BSTRING_SIZE (length);
207
208 return &new->d.data;
209 }
c906108c
SS
210}
211
c2d11a7d 212\f
af5f3db6
AC
213/* Allocating and freeing bcaches. */
214
215struct bcache *
216bcache_xmalloc (void)
217{
218 /* Allocate the bcache pre-zeroed. */
219 struct bcache *b = XCALLOC (1, struct bcache);
220 obstack_specify_allocation (&b->cache, 0, 0, xmalloc, xfree);
221 return b;
222}
c2d11a7d
JM
223
224/* Free all the storage associated with BCACHE. */
c906108c 225void
af5f3db6 226bcache_xfree (struct bcache *bcache)
c906108c 227{
af5f3db6
AC
228 if (bcache == NULL)
229 return;
c2d11a7d 230 obstack_free (&bcache->cache, 0);
af5f3db6
AC
231 xfree (bcache->bucket);
232 xfree (bcache);
c2d11a7d
JM
233}
234
235
236\f
237/* Printing statistics. */
238
239static int
240compare_ints (const void *ap, const void *bp)
241{
242 /* Because we know we're comparing two ints which are positive,
243 there's no danger of overflow here. */
244 return * (int *) ap - * (int *) bp;
245}
246
247
248static void
249print_percentage (int portion, int total)
250{
251 if (total == 0)
252 printf_filtered ("(not applicable)\n");
c906108c 253 else
c2d11a7d
JM
254 printf_filtered ("%3d%%\n", portion * 100 / total);
255}
256
257
258/* Print statistics on BCACHE's memory usage and efficacity at
259 eliminating duplication. NAME should describe the kind of data
260 BCACHE holds. Statistics are printed using `printf_filtered' and
261 its ilk. */
262void
263print_bcache_statistics (struct bcache *c, char *type)
264{
265 int occupied_buckets;
266 int max_chain_length;
267 int median_chain_length;
268
269 /* Count the number of occupied buckets, and measure chain lengths. */
270 {
745b8ca0 271 unsigned int b;
c2d11a7d
JM
272 int *chain_length
273 = (int *) alloca (c->num_buckets * sizeof (*chain_length));
274
275 occupied_buckets = 0;
276
277 for (b = 0; b < c->num_buckets; b++)
278 {
279 struct bstring *s = c->bucket[b];
280
281 chain_length[b] = 0;
282
283 if (s)
284 {
285 occupied_buckets++;
286
287 while (s)
288 {
289 chain_length[b]++;
290 s = s->next;
291 }
292 }
293 }
294
295 /* To compute the median, we need the set of chain lengths sorted. */
296 qsort (chain_length, c->num_buckets, sizeof (chain_length[0]),
297 compare_ints);
298
299 if (c->num_buckets > 0)
300 {
301 max_chain_length = chain_length[c->num_buckets - 1];
302 median_chain_length = chain_length[c->num_buckets / 2];
303 }
304 else
305 {
306 max_chain_length = 0;
307 median_chain_length = 0;
308 }
309 }
310
311 printf_filtered (" Cached '%s' statistics:\n", type);
312 printf_filtered (" Total object count: %ld\n", c->total_count);
745b8ca0 313 printf_filtered (" Unique object count: %lu\n", c->unique_count);
c2d11a7d
JM
314 printf_filtered (" Percentage of duplicates, by count: ");
315 print_percentage (c->total_count - c->unique_count, c->total_count);
316 printf_filtered ("\n");
317
318 printf_filtered (" Total object size: %ld\n", c->total_size);
319 printf_filtered (" Unique object size: %ld\n", c->unique_size);
320 printf_filtered (" Percentage of duplicates, by size: ");
321 print_percentage (c->total_size - c->unique_size, c->total_size);
322 printf_filtered ("\n");
323
324 printf_filtered (" Total memory used by bcache, including overhead: %ld\n",
325 c->structure_size);
326 printf_filtered (" Percentage memory overhead: ");
327 print_percentage (c->structure_size - c->unique_size, c->unique_size);
328 printf_filtered (" Net memory savings: ");
329 print_percentage (c->total_size - c->structure_size, c->total_size);
330 printf_filtered ("\n");
331
332 printf_filtered (" Hash table size: %3d\n", c->num_buckets);
333 printf_filtered (" Hash table population: ");
334 print_percentage (occupied_buckets, c->num_buckets);
335 printf_filtered (" Median hash chain length: %3d\n",
336 median_chain_length);
337 printf_filtered (" Average hash chain length: ");
338 if (c->num_buckets > 0)
745b8ca0 339 printf_filtered ("%3lu\n", c->unique_count / c->num_buckets);
c906108c 340 else
c2d11a7d
JM
341 printf_filtered ("(not applicable)\n");
342 printf_filtered (" Maximum hash chain length: %3d\n", max_chain_length);
343 printf_filtered ("\n");
c906108c 344}
af5f3db6
AC
345
346int
347bcache_memory_used (struct bcache *bcache)
348{
349 return obstack_memory_used (&bcache->cache);
350}
This page took 0.258042 seconds and 4 git commands to generate.