]> git.saurik.com Git - bison.git/blame - lib/bitset_stats.c
Update.
[bison.git] / lib / bitset_stats.c
CommitLineData
613f5e1a
AD
1/* Bitset statistics.
2 Copyright (C) 2002 Free Software Foundation, Inc.
3 Contributed by Michael Hayes (m.hayes@elec.canterbury.ac.nz).
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18*/
19
20/* This file is a wrapper bitset implementation for the other bitset
21 implementations. It provides bitset compatibility checking and
22 statistics gathering without having to instrument the bitset
23 implementations. When statistics gathering is enabled, the bitset
24 operations get vectored through here and we then call the appropriate
25 routines.
26*/
27
28#ifdef HAVE_CONFIG_H
29#include "config.h"
30#endif
31
32#include "bbitset.h"
33#include "abitset.h"
34#include "ebitset.h"
35#include "lbitset.h"
36#include "bitset_stats.h"
37#include <stdlib.h>
38#include <string.h>
39#include <stdio.h>
40
c131cbff
PE
41#include "gettext.h"
42#define _(Msgid) gettext (Msgid)
613f5e1a
AD
43
44/* Configuration macros. */
45#define BITSET_STATS_FILE "bitset.dat"
46#define BITSET_LOG_COUNT_BINS 10
47#define BITSET_LOG_SIZE_BINS 16
48#define BITSET_DENSITY_BINS 20
49
50
51/* Accessor macros. */
52#define BITSET_STATS_ALLOCS_INC(TYPE) \
53 bitset_stats_info->types[(TYPE)].allocs++
54#define BITSET_STATS_FREES_INC(BSET) \
55 bitset_stats_info->types[BITSET_TYPE_ (BSET)].frees++
56#define BITSET_STATS_SETS_INC(BSET) \
57 bitset_stats_info->types[BITSET_TYPE_ (BSET)].sets++
58#define BITSET_STATS_CACHE_SETS_INC(BSET) \
59 bitset_stats_info->types[BITSET_TYPE_ (BSET)].cache_sets++
60#define BITSET_STATS_RESETS_INC(BSET) \
61 bitset_stats_info->types[BITSET_TYPE_ (BSET)].resets++
62#define BITSET_STATS_CACHE_RESETS_INC(BSET) \
63 bitset_stats_info->types[BITSET_TYPE_ (BSET)].cache_resets++
64#define BITSET_STATS_TESTS_INC(BSET) \
65 bitset_stats_info->types[BITSET_TYPE_ (BSET)].tests++
66#define BITSET_STATS_CACHE_TESTS_INC(BSET) \
67 bitset_stats_info->types[BITSET_TYPE_ (BSET)].cache_tests++
68#define BITSET_STATS_LISTS_INC(BSET) \
69 bitset_stats_info->types[BITSET_TYPE_ (BSET)].lists++
70#define BITSET_STATS_LIST_COUNTS_INC(BSET, I) \
71 bitset_stats_info->types[BITSET_TYPE_ (BSET)].list_counts[(I)]++
72#define BITSET_STATS_LIST_SIZES_INC(BSET, I) \
73 bitset_stats_info->types[BITSET_TYPE_ (BSET)].list_sizes[(I)]++
74#define BITSET_STATS_LIST_DENSITY_INC(BSET, I) \
75 bitset_stats_info->types[BITSET_TYPE_ (BSET)].list_density[(I)]++
76
77
78typedef struct bitset_stats_struct
79{
80 bitset bset;
81} *bitset_stats;
82
83
84struct bitset_struct
85{
86 struct bbitset_struct b;
87 struct bitset_stats_struct s;
88};
89
90
91struct bitset_type_info_struct
92{
93 unsigned int allocs;
94 unsigned int frees;
95 unsigned int lists;
96 unsigned int sets;
97 unsigned int cache_sets;
98 unsigned int resets;
99 unsigned int cache_resets;
100 unsigned int tests;
101 unsigned int cache_tests;
102 unsigned int list_counts[BITSET_LOG_COUNT_BINS];
103 unsigned int list_sizes[BITSET_LOG_SIZE_BINS];
104 unsigned int list_density[BITSET_DENSITY_BINS];
105};
106
107struct bitset_stats_info_struct
108{
109 unsigned int runs;
110 struct bitset_type_info_struct types[BITSET_TYPE_NUM];
111};
112
113
114struct bitset_stats_info_struct bitset_stats_info_data;
115struct bitset_stats_info_struct *bitset_stats_info;
116int bitset_stats_enabled = 0;
117
118
119static void bitset_stats_set PARAMS ((bitset, bitset_bindex));
120static void bitset_stats_reset PARAMS ((bitset, bitset_bindex));
121static int bitset_stats_test PARAMS ((bitset, bitset_bindex));
122static int bitset_stats_size PARAMS ((bitset));
123static int bitset_stats_op1 PARAMS ((bitset, enum bitset_ops));
124static int bitset_stats_op2 PARAMS ((bitset, bitset, enum bitset_ops));
125static int bitset_stats_op3 PARAMS ((bitset, bitset, bitset, enum bitset_ops));
126static int bitset_stats_op4 PARAMS ((bitset, bitset, bitset, bitset,
127 enum bitset_ops));
128static int bitset_stats_list PARAMS ((bitset, bitset_bindex *, bitset_bindex,
129 bitset_bindex *));
130static int bitset_stats_reverse_list
131PARAMS ((bitset, bitset_bindex *, bitset_bindex, bitset_bindex *));
132static void bitset_stats_free PARAMS ((bitset));
133static void bitset_percent_histogram_print PARAMS ((FILE *, const char *,
134 const char *,
135 unsigned int,
136 unsigned int *));
137static void bitset_log_histogram_print PARAMS ((FILE *, const char *,
138 const char *,
139 unsigned int,
140 unsigned int *));
141static void bitset_stats_print_1
142PARAMS ((FILE *, const char *, struct bitset_type_info_struct *));
143static void bitset_stats_print PARAMS ((FILE *, int));
144
145
146/* Print a percentage histogram with message MSG to FILE. */
147static void
148bitset_percent_histogram_print (file, name, msg, n_bins, bins)
149 FILE *file;
150 const char *name;
151 const char *msg;
152 unsigned int n_bins;
153 unsigned int *bins;
154{
155 unsigned int i;
156 unsigned int total;
157
158 total = 0;
159 for (i = 0; i < n_bins; i++)
160 total += bins[i];
161
162 if (!total)
163 return;
164
165 fprintf (file, "%s %s", name, msg);
166 for (i = 0; i < n_bins; i++)
167 fprintf (file, "%.0f-%.0f%%\t%8d (%5.1f%%)\n",
168 i * 100.0 / n_bins,
169 (i + 1) * 100.0 / n_bins, bins[i],
170 (100.0 * bins[i]) / total);
171}
172
173
174/* Print a log histogram with message MSG to FILE. */
175static void
176bitset_log_histogram_print (file, name, msg, n_bins, bins)
177 FILE *file;
178 const char *name;
179 const char *msg;
180 unsigned int n_bins;
181 unsigned int *bins;
182{
183 unsigned int i;
184 unsigned int total;
185 unsigned int max_width;
186 unsigned int last_bin;
187
188 total = 0;
189 for (i = 0; i < n_bins; i++)
190 total += bins[i];
191
192 if (!total)
193 return;
194
195 for (i = n_bins; i > 3 && ! bins[i - 1]; i--)
196 continue;
197 last_bin = i - 1;
198
199 /* 2 * ceil (log10 (2) * (N - 1)) + 1. */
200 max_width = 2 * (unsigned int) (0.30103 * (n_bins - 1) + 0.9999) + 1;
201
202 fprintf (file, "%s %s", name, msg);
203 for (i = 0; i < 2; i++)
204 fprintf (file, "%*d\t%8d (%5.1f%%)\n",
205 max_width, i, bins[i], 100.0 * bins[i] / total);
206
207 for (; i <= last_bin; i++)
208 fprintf (file, "%*d-%d\t%8d (%5.1f%%)\n",
209 max_width - ((unsigned int) (0.30103 * (i) + 0.9999) + 1),
210 1 << (i - 1), (1 << i) - 1, bins[i],
211 (100.0 * bins[i]) / total);
212}
213
214
215/* Print bitset statistics to FILE. */
216static void
217bitset_stats_print_1 (file, name, stats)
218 FILE *file;
219 const char *name;
220 struct bitset_type_info_struct *stats;
221{
222 if (!stats)
223 return;
224
225 fprintf (file, "%s:\n", name);
c131cbff 226 fprintf (file, _("%d bitset_allocs, %d freed (%.2f%%).\n"),
613f5e1a
AD
227 stats->allocs, stats->frees,
228 stats->allocs ? 100.0 * stats->frees / stats->allocs : 0);
c131cbff 229 fprintf (file, _("%d bitset_sets, %d cached (%.2f%%)\n"),
613f5e1a
AD
230 stats->sets, stats->cache_sets,
231 stats->sets ? 100.0 * stats->cache_sets / stats->sets : 0);
c131cbff 232 fprintf (file, _("%d bitset_resets, %d cached (%.2f%%)\n"),
613f5e1a
AD
233 stats->resets, stats->cache_resets,
234 stats->resets ? 100.0 * stats->cache_resets / stats->resets : 0);
c131cbff 235 fprintf (file, _("%d bitset_tests, %d cached (%.2f%%)\n"),
613f5e1a
AD
236 stats->tests, stats->cache_tests,
237 stats->tests ? 100.0 * stats->cache_tests / stats->tests : 0);
238
c131cbff 239 fprintf (file, _("%d bitset_lists\n"), stats->lists);
613f5e1a 240
c131cbff 241 bitset_log_histogram_print (file, name, _("count log histogram\n"),
613f5e1a
AD
242 BITSET_LOG_COUNT_BINS, stats->list_counts);
243
c131cbff 244 bitset_log_histogram_print (file, name, _("size log histogram\n"),
613f5e1a
AD
245 BITSET_LOG_SIZE_BINS, stats->list_sizes);
246
c131cbff 247 bitset_percent_histogram_print (file, name, _("density histogram\n"),
613f5e1a
AD
248 BITSET_DENSITY_BINS, stats->list_density);
249}
250
251
252/* Print all bitset statistics to FILE. */
253static void
254bitset_stats_print (file, verbose)
255 FILE *file;
256 int verbose ATTRIBUTE_UNUSED;
257{
258 int i;
259 static const char *names[] = BITSET_TYPE_NAMES;
260
261 if (!bitset_stats_info)
262 return;
263
c131cbff 264 fprintf (file, _("Bitset statistics:\n\n"));
613f5e1a
AD
265
266 if (bitset_stats_info->runs > 1)
c131cbff 267 fprintf (file, _("Accumulated runs = %d\n"), bitset_stats_info->runs);
613f5e1a
AD
268
269 for (i = 0; i < BITSET_TYPE_NUM; i++)
270 bitset_stats_print_1 (file, names[i], &bitset_stats_info->types[i]);
271}
272
273
274/* Initialise bitset statistics logging. */
275void
276bitset_stats_enable ()
277{
278 if (!bitset_stats_info)
279 bitset_stats_info = &bitset_stats_info_data;
280 bitset_stats_enabled = 1;
281}
282
283
284void
285bitset_stats_disable ()
286{
287 bitset_stats_enabled = 0;
288}
289
290
291/* Read bitset statistics file. */
292void
293bitset_stats_read (filename)
294 const char *filename;
295{
296 FILE *file;
297
298 if (!bitset_stats_info)
299 return;
300
301 if (!filename)
302 filename = BITSET_STATS_FILE;
303
304 file = fopen (filename, "r");
305 if (file)
306 {
307 if (fread (&bitset_stats_info_data, sizeof (bitset_stats_info_data),
308 1, file) != 1)
309 {
310 if (ferror (file))
c131cbff 311 perror (_("Could not read stats file."));
613f5e1a 312 else
c131cbff 313 fprintf (stderr, _("Bad stats file size.\n"));
613f5e1a
AD
314 }
315 fclose (file);
316 }
317 bitset_stats_info_data.runs++;
318}
319
320
321/* Write bitset statistics file. */
322void
323bitset_stats_write (filename)
324 const char *filename;
325{
326 FILE *file;
327
328 if (!bitset_stats_info)
329 return;
330
331 if (!filename)
332 filename = BITSET_STATS_FILE;
333
334 file = fopen (filename, "w");
335 if (file)
336 {
337 if (fwrite (&bitset_stats_info_data, sizeof (bitset_stats_info_data),
338 1, file) != 1)
c131cbff 339 perror (_("Could not write stats file."));
613f5e1a
AD
340 fclose (file);
341 }
342 else
c131cbff 343 perror (_("Could not open stats file for writing."));
613f5e1a
AD
344}
345
346
347/* Dump bitset statistics to FILE. */
348void
349bitset_stats_dump (file)
350 FILE *file;
351{
352 bitset_stats_print (file, 0);
353}
354
355
356/* Function to be called from debugger to print bitset stats. */
357void
358debug_bitset_stats (void)
359{
360 bitset_stats_print (stderr, 1);
361}
362
363
364static void
365bitset_stats_set (dst, bitno)
366 bitset dst;
367 bitset_bindex bitno;
368{
369 bitset bset = dst->s.bset;
c131cbff
PE
370 bitset_windex wordno = bitno / BITSET_WORD_BITS;
371 bitset_windex offset = wordno - bset->b.cindex;
613f5e1a
AD
372
373 BITSET_STATS_SETS_INC (bset);
374
375 if (offset < bset->b.csize)
376 {
c131cbff 377 bset->b.cdata[offset] |= (bitset_word) 1 << (bitno % BITSET_WORD_BITS);
613f5e1a
AD
378 BITSET_STATS_CACHE_SETS_INC (bset);
379 }
380 else
381 BITSET_SET_ (bset, bitno);
382}
383
384
385static void
386bitset_stats_reset (dst, bitno)
387 bitset dst;
388 bitset_bindex bitno;
389{
390 bitset bset = dst->s.bset;
c131cbff
PE
391 bitset_windex wordno = bitno / BITSET_WORD_BITS;
392 bitset_windex offset = wordno - bset->b.cindex;
613f5e1a
AD
393
394 BITSET_STATS_RESETS_INC (bset);
395
396 if (offset < bset->b.csize)
397 {
c131cbff
PE
398 bset->b.cdata[offset] &=
399 ~((bitset_word) 1 << (bitno % BITSET_WORD_BITS));
613f5e1a
AD
400 BITSET_STATS_CACHE_RESETS_INC (bset);
401 }
402 else
403 BITSET_RESET_ (bset, bitno);
404}
405
406
407static int
408bitset_stats_test (src, bitno)
409 bitset src;
410 bitset_bindex bitno;
411{
412 bitset bset = src->s.bset;
c131cbff
PE
413 bitset_windex wordno = bitno / BITSET_WORD_BITS;
414 bitset_windex offset = wordno - bset->b.cindex;
613f5e1a
AD
415
416 BITSET_STATS_TESTS_INC (bset);
417
418 if (offset < bset->b.csize)
419 {
420 BITSET_STATS_CACHE_TESTS_INC (bset);
421 return (bset->b.cdata[offset] >> (bitno % BITSET_WORD_BITS)) & 1;
422 }
423 else
424 return BITSET_TEST_ (bset, bitno);
425}
426
427
428static int
429bitset_stats_size (src)
430 bitset src;
431{
432 return BITSET_SIZE_ (src->s.bset);
433}
434
435
436static int
437bitset_stats_op1 (dst, op)
438 bitset dst;
439 enum bitset_ops op;
440{
441 return BITSET_OP1_ (dst->s.bset, op);
442}
443
444
445static int
446bitset_stats_op2 (dst, src, op)
447 bitset dst;
448 bitset src;
449 enum bitset_ops op;
450{
451 BITSET_CHECK2_ (dst, src);
452 return BITSET_OP2_ (dst->s.bset, src->s.bset, op);
453}
454
455
456static int
457bitset_stats_op3 (dst, src1, src2, op)
458 bitset dst;
459 bitset src1;
460 bitset src2;
461 enum bitset_ops op;
462{
463 BITSET_CHECK3_ (dst, src1, src2);
464 return BITSET_OP3_ (dst->s.bset, src1->s.bset, src2->s.bset, op);
465}
466
467
468static int
469bitset_stats_op4 (dst, src1, src2, src3, op)
470 bitset dst;
471 bitset src1;
472 bitset src2;
473 bitset src3;
474 enum bitset_ops op;
475{
476 BITSET_CHECK4_ (dst, src1, src2, src3);
477
478 /* This is a bit of a hack. If the implementation handles
479 a four operand operation then vector to it, passing
480 the enclosed bitsets. Otherwise use the fallback
481 bitset_op4 routine. */
482 if (dst->s.bset->b.ops->op4 != bitset_op4)
483 return BITSET_OP4_ (dst->s.bset, src1->s.bset, src2->s.bset,
484 src3->s.bset, op);
485
486 return bitset_op4 (dst, src1, src2, src3, op);
487}
488
489
490static int
491bitset_stats_list (bset, list, num, next)
492 bitset bset;
493 bitset_bindex *list;
494 bitset_bindex num;
495 bitset_bindex *next;
496{
497 bitset_bindex count;
498 bitset_bindex tmp;
499 bitset_bindex size;
500 bitset_bindex i;
501 enum bitset_type type;
502
503 count = BITSET_LIST_ (bset->s.bset, list, num, next);
504
505 type = BITSET_TYPE_ (bset->s.bset);
506 BITSET_STATS_LISTS_INC (bset->s.bset);
507
508 /* Log histogram of number of set bits. */
509 for (i = 0, tmp = count; tmp; tmp >>= 1, i++)
510 continue;
511 if (i >= BITSET_LOG_COUNT_BINS)
512 i = BITSET_LOG_COUNT_BINS - 1;
513 BITSET_STATS_LIST_COUNTS_INC (bset->s.bset, i);
514
515 /* Log histogram of number of bits in set. */
516 size = BITSET_SIZE_ (bset->s.bset);
517 for (i = 0, tmp = size; tmp; tmp >>= 1, i++)
518 continue;
519 if (i >= BITSET_LOG_SIZE_BINS)
520 i = BITSET_LOG_SIZE_BINS - 1;
521 BITSET_STATS_LIST_SIZES_INC (bset->s.bset, i);
522
523 /* Histogram of fraction of bits set. */
524 i = size ? (count * BITSET_DENSITY_BINS) / size : 0;
525 if (i >= BITSET_DENSITY_BINS)
526 i = BITSET_DENSITY_BINS - 1;
527 BITSET_STATS_LIST_DENSITY_INC (bset->s.bset, i);
528 return count;
529}
530
531
532static int
533bitset_stats_reverse_list (bset, list, num, next)
534 bitset bset;
535 bitset_bindex *list;
536 bitset_bindex num;
537 bitset_bindex *next;
538{
539 return BITSET_REVERSE_LIST_ (bset->s.bset, list, num, next);
540}
541
542
543static void
544bitset_stats_free (bset)
545 bitset bset;
546{
547 BITSET_STATS_FREES_INC (bset->s.bset);
548 BITSET_FREE_ (bset->s.bset);
549}
550
551
552struct bitset_ops_struct bitset_stats_ops = {
553 bitset_stats_set,
554 bitset_stats_reset,
555 bitset_stats_test,
556 bitset_stats_size,
557 bitset_stats_op1,
558 bitset_stats_op2,
559 bitset_stats_op3,
560 bitset_stats_op4,
561 bitset_stats_list,
562 bitset_stats_reverse_list,
563 bitset_stats_free,
564 BITSET_STATS
565};
566
567
568/* Return enclosed bitset type. */
569enum bitset_type
570bitset_stats_type_get (bset)
571 bitset bset;
572{
573 return BITSET_TYPE_ (bset->s.bset);
574}
575
576
577int bitset_stats_bytes (void)
578{
579 return sizeof (struct bitset_struct);
580}
581
582
583bitset
584bitset_stats_init (bset, n_bits, type)
585 bitset bset;
586 bitset_bindex n_bits;
587 enum bitset_type type;
588{
589 unsigned int bytes;
590 bitset sbset;
591
592 bset->b.ops = &bitset_stats_ops;
593
594 /* Disable cache. */
595 bset->b.cindex = 0;
596 bset->b.csize = 0;
597 bset->b.cdata = 0;
598
599 /* Set up the actual bitset implementation that
600 we are a wrapper over. */
601 switch (type)
602 {
603 case BITSET_ARRAY:
604 bytes = abitset_bytes (n_bits);
605 sbset = (bitset) xcalloc (1, bytes);
606 abitset_init (sbset, n_bits);
607 break;
608
609 case BITSET_LIST:
610 bytes = lbitset_bytes (n_bits);
611 sbset = (bitset) xcalloc (1, bytes);
612 lbitset_init (sbset, n_bits);
613 break;
614
615 case BITSET_TABLE:
616 bytes = ebitset_bytes (n_bits);
617 sbset = (bitset) xcalloc (1, bytes);
618 ebitset_init (sbset, n_bits);
619 break;
620
621 default:
622 abort ();
623 }
624
625 bset->s.bset = sbset;
626
627 BITSET_STATS_ALLOCS_INC (type);
628
629 return bset;
630}