]> git.saurik.com Git - bison.git/blame_incremental - lib/bitset_stats.c
* data/push.c (yyparse): Remove the prototype and the #define when in
[bison.git] / lib / bitset_stats.c
... / ...
CommitLineData
1/* Bitset statistics.
2 Copyright (C) 2002, 2003, 2004, 2005, 2006 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 Foundation,
17 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
18
19/* This file is a wrapper bitset implementation for the other bitset
20 implementations. It provides bitset compatibility checking and
21 statistics gathering without having to instrument the bitset
22 implementations. When statistics gathering is enabled, the bitset
23 operations get vectored through here and we then call the appropriate
24 routines. */
25
26#include <config.h>
27
28#include "bitset_stats.h"
29
30#include "bbitset.h"
31#include "abitset.h"
32#include "ebitset.h"
33#include "lbitset.h"
34#include "vbitset.h"
35#include <stdlib.h>
36#include <string.h>
37#include <stdio.h>
38
39#include "gettext.h"
40#define _(Msgid) gettext (Msgid)
41
42/* Configuration macros. */
43#define BITSET_STATS_FILE "bitset.dat"
44#define BITSET_LOG_COUNT_BINS 10
45#define BITSET_LOG_SIZE_BINS 16
46#define BITSET_DENSITY_BINS 20
47
48
49/* Accessor macros. */
50#define BITSET_STATS_ALLOCS_INC(TYPE) \
51 bitset_stats_info->types[(TYPE)].allocs++
52#define BITSET_STATS_FREES_INC(BSET) \
53 bitset_stats_info->types[BITSET_TYPE_ (BSET)].frees++
54#define BITSET_STATS_SETS_INC(BSET) \
55 bitset_stats_info->types[BITSET_TYPE_ (BSET)].sets++
56#define BITSET_STATS_CACHE_SETS_INC(BSET) \
57 bitset_stats_info->types[BITSET_TYPE_ (BSET)].cache_sets++
58#define BITSET_STATS_RESETS_INC(BSET) \
59 bitset_stats_info->types[BITSET_TYPE_ (BSET)].resets++
60#define BITSET_STATS_CACHE_RESETS_INC(BSET) \
61 bitset_stats_info->types[BITSET_TYPE_ (BSET)].cache_resets++
62#define BITSET_STATS_TESTS_INC(BSET) \
63 bitset_stats_info->types[BITSET_TYPE_ (BSET)].tests++
64#define BITSET_STATS_CACHE_TESTS_INC(BSET) \
65 bitset_stats_info->types[BITSET_TYPE_ (BSET)].cache_tests++
66#define BITSET_STATS_LISTS_INC(BSET) \
67 bitset_stats_info->types[BITSET_TYPE_ (BSET)].lists++
68#define BITSET_STATS_LIST_COUNTS_INC(BSET, I) \
69 bitset_stats_info->types[BITSET_TYPE_ (BSET)].list_counts[(I)]++
70#define BITSET_STATS_LIST_SIZES_INC(BSET, I) \
71 bitset_stats_info->types[BITSET_TYPE_ (BSET)].list_sizes[(I)]++
72#define BITSET_STATS_LIST_DENSITY_INC(BSET, I) \
73 bitset_stats_info->types[BITSET_TYPE_ (BSET)].list_density[(I)]++
74
75
76struct bitset_type_info_struct
77{
78 unsigned int allocs;
79 unsigned int frees;
80 unsigned int lists;
81 unsigned int sets;
82 unsigned int cache_sets;
83 unsigned int resets;
84 unsigned int cache_resets;
85 unsigned int tests;
86 unsigned int cache_tests;
87 unsigned int list_counts[BITSET_LOG_COUNT_BINS];
88 unsigned int list_sizes[BITSET_LOG_SIZE_BINS];
89 unsigned int list_density[BITSET_DENSITY_BINS];
90};
91
92struct bitset_stats_info_struct
93{
94 unsigned int runs;
95 struct bitset_type_info_struct types[BITSET_TYPE_NUM];
96};
97
98
99struct bitset_stats_info_struct bitset_stats_info_data;
100struct bitset_stats_info_struct *bitset_stats_info;
101bool bitset_stats_enabled = false;
102
103
104/* Print a percentage histogram with message MSG to FILE. */
105static void
106bitset_percent_histogram_print (FILE *file, const char *name, const char *msg,
107 unsigned int n_bins, unsigned int *bins)
108{
109 unsigned int i;
110 unsigned int total;
111
112 total = 0;
113 for (i = 0; i < n_bins; i++)
114 total += bins[i];
115
116 if (!total)
117 return;
118
119 fprintf (file, "%s %s", name, msg);
120 for (i = 0; i < n_bins; i++)
121 fprintf (file, "%.0f-%.0f%%\t%8u (%5.1f%%)\n",
122 i * 100.0 / n_bins,
123 (i + 1) * 100.0 / n_bins, bins[i],
124 (100.0 * bins[i]) / total);
125}
126
127
128/* Print a log histogram with message MSG to FILE. */
129static void
130bitset_log_histogram_print (FILE *file, const char *name, const char *msg,
131 unsigned int n_bins, unsigned int *bins)
132{
133 unsigned int i;
134 unsigned int total;
135 unsigned int max_width;
136
137 total = 0;
138 for (i = 0; i < n_bins; i++)
139 total += bins[i];
140
141 if (!total)
142 return;
143
144 /* Determine number of useful bins. */
145 for (i = n_bins; i > 3 && ! bins[i - 1]; i--)
146 continue;
147 n_bins = i;
148
149 /* 2 * ceil (log10 (2) * (N - 1)) + 1. */
150 max_width = 2 * (unsigned int) (0.30103 * (n_bins - 1) + 0.9999) + 1;
151
152 fprintf (file, "%s %s", name, msg);
153 for (i = 0; i < 2; i++)
154 fprintf (file, "%*d\t%8u (%5.1f%%)\n",
155 max_width, i, bins[i], 100.0 * bins[i] / total);
156
157 for (; i < n_bins; i++)
158 fprintf (file, "%*lu-%lu\t%8u (%5.1f%%)\n",
159 max_width - ((unsigned int) (0.30103 * (i) + 0.9999) + 1),
160 1UL << (i - 1),
161 (1UL << i) - 1,
162 bins[i],
163 (100.0 * bins[i]) / total);
164}
165
166
167/* Print bitset statistics to FILE. */
168static void
169bitset_stats_print_1 (FILE *file, const char *name,
170 struct bitset_type_info_struct *stats)
171{
172 if (!stats)
173 return;
174
175 fprintf (file, "%s:\n", name);
176 fprintf (file, _("%u bitset_allocs, %u freed (%.2f%%).\n"),
177 stats->allocs, stats->frees,
178 stats->allocs ? 100.0 * stats->frees / stats->allocs : 0);
179 fprintf (file, _("%u bitset_sets, %u cached (%.2f%%)\n"),
180 stats->sets, stats->cache_sets,
181 stats->sets ? 100.0 * stats->cache_sets / stats->sets : 0);
182 fprintf (file, _("%u bitset_resets, %u cached (%.2f%%)\n"),
183 stats->resets, stats->cache_resets,
184 stats->resets ? 100.0 * stats->cache_resets / stats->resets : 0);
185 fprintf (file, _("%u bitset_tests, %u cached (%.2f%%)\n"),
186 stats->tests, stats->cache_tests,
187 stats->tests ? 100.0 * stats->cache_tests / stats->tests : 0);
188
189 fprintf (file, _("%u bitset_lists\n"), stats->lists);
190
191 bitset_log_histogram_print (file, name, _("count log histogram\n"),
192 BITSET_LOG_COUNT_BINS, stats->list_counts);
193
194 bitset_log_histogram_print (file, name, _("size log histogram\n"),
195 BITSET_LOG_SIZE_BINS, stats->list_sizes);
196
197 bitset_percent_histogram_print (file, name, _("density histogram\n"),
198 BITSET_DENSITY_BINS, stats->list_density);
199}
200
201
202/* Print all bitset statistics to FILE. */
203static void
204bitset_stats_print (FILE *file, bool verbose ATTRIBUTE_UNUSED)
205{
206 int i;
207
208 if (!bitset_stats_info)
209 return;
210
211 fprintf (file, _("Bitset statistics:\n\n"));
212
213 if (bitset_stats_info->runs > 1)
214 fprintf (file, _("Accumulated runs = %u\n"), bitset_stats_info->runs);
215
216 for (i = 0; i < BITSET_TYPE_NUM; i++)
217 bitset_stats_print_1 (file, bitset_type_names[i],
218 &bitset_stats_info->types[i]);
219}
220
221
222/* Initialise bitset statistics logging. */
223void
224bitset_stats_enable (void)
225{
226 if (!bitset_stats_info)
227 bitset_stats_info = &bitset_stats_info_data;
228 bitset_stats_enabled = true;
229}
230
231
232void
233bitset_stats_disable (void)
234{
235 bitset_stats_enabled = false;
236}
237
238
239/* Read bitset statistics file. */
240void
241bitset_stats_read (const char *file_name)
242{
243 FILE *file;
244
245 if (!bitset_stats_info)
246 return;
247
248 if (!file_name)
249 file_name = BITSET_STATS_FILE;
250
251 file = fopen (file_name, "r");
252 if (file)
253 {
254 if (fread (&bitset_stats_info_data, sizeof (bitset_stats_info_data),
255 1, file) != 1)
256 {
257 if (ferror (file))
258 perror (_("Could not read stats file."));
259 else
260 fprintf (stderr, _("Bad stats file size.\n"));
261 }
262 if (fclose (file) != 0)
263 perror (_("Could not read stats file."));
264 }
265 bitset_stats_info_data.runs++;
266}
267
268
269/* Write bitset statistics file. */
270void
271bitset_stats_write (const char *file_name)
272{
273 FILE *file;
274
275 if (!bitset_stats_info)
276 return;
277
278 if (!file_name)
279 file_name = BITSET_STATS_FILE;
280
281 file = fopen (file_name, "w");
282 if (file)
283 {
284 if (fwrite (&bitset_stats_info_data, sizeof (bitset_stats_info_data),
285 1, file) != 1)
286 perror (_("Could not write stats file."));
287 if (fclose (file) != 0)
288 perror (_("Could not write stats file."));
289 }
290 else
291 perror (_("Could not open stats file for writing."));
292}
293
294
295/* Dump bitset statistics to FILE. */
296void
297bitset_stats_dump (FILE *file)
298{
299 bitset_stats_print (file, false);
300}
301
302
303/* Function to be called from debugger to print bitset stats. */
304void
305debug_bitset_stats (void)
306{
307 bitset_stats_print (stderr, true);
308}
309
310
311static void
312bitset_stats_set (bitset dst, bitset_bindex bitno)
313{
314 bitset bset = dst->s.bset;
315 bitset_windex wordno = bitno / BITSET_WORD_BITS;
316 bitset_windex offset = wordno - bset->b.cindex;
317
318 BITSET_STATS_SETS_INC (bset);
319
320 if (offset < bset->b.csize)
321 {
322 bset->b.cdata[offset] |= (bitset_word) 1 << (bitno % BITSET_WORD_BITS);
323 BITSET_STATS_CACHE_SETS_INC (bset);
324 }
325 else
326 BITSET_SET_ (bset, bitno);
327}
328
329
330static void
331bitset_stats_reset (bitset dst, bitset_bindex bitno)
332{
333 bitset bset = dst->s.bset;
334 bitset_windex wordno = bitno / BITSET_WORD_BITS;
335 bitset_windex offset = wordno - bset->b.cindex;
336
337 BITSET_STATS_RESETS_INC (bset);
338
339 if (offset < bset->b.csize)
340 {
341 bset->b.cdata[offset] &=
342 ~((bitset_word) 1 << (bitno % BITSET_WORD_BITS));
343 BITSET_STATS_CACHE_RESETS_INC (bset);
344 }
345 else
346 BITSET_RESET_ (bset, bitno);
347}
348
349
350static bool
351bitset_stats_toggle (bitset src, bitset_bindex bitno)
352{
353 return BITSET_TOGGLE_ (src->s.bset, bitno);
354}
355
356
357static bool
358bitset_stats_test (bitset src, bitset_bindex bitno)
359{
360 bitset bset = src->s.bset;
361 bitset_windex wordno = bitno / BITSET_WORD_BITS;
362 bitset_windex offset = wordno - bset->b.cindex;
363
364 BITSET_STATS_TESTS_INC (bset);
365
366 if (offset < bset->b.csize)
367 {
368 BITSET_STATS_CACHE_TESTS_INC (bset);
369 return (bset->b.cdata[offset] >> (bitno % BITSET_WORD_BITS)) & 1;
370 }
371 else
372 return BITSET_TEST_ (bset, bitno);
373}
374
375
376static bitset_bindex
377bitset_stats_resize (bitset src, bitset_bindex size)
378{
379 return BITSET_RESIZE_ (src->s.bset, size);
380}
381
382
383static bitset_bindex
384bitset_stats_size (bitset src)
385{
386 return BITSET_SIZE_ (src->s.bset);
387}
388
389
390static bitset_bindex
391bitset_stats_count (bitset src)
392{
393 return BITSET_COUNT_ (src->s.bset);
394}
395
396
397static bool
398bitset_stats_empty_p (bitset dst)
399{
400 return BITSET_EMPTY_P_ (dst->s.bset);
401}
402
403
404static void
405bitset_stats_ones (bitset dst)
406{
407 BITSET_ONES_ (dst->s.bset);
408}
409
410
411static void
412bitset_stats_zero (bitset dst)
413{
414 BITSET_ZERO_ (dst->s.bset);
415}
416
417
418static void
419bitset_stats_copy (bitset dst, bitset src)
420{
421 BITSET_CHECK2_ (dst, src);
422 BITSET_COPY_ (dst->s.bset, src->s.bset);
423}
424
425
426static bool
427bitset_stats_disjoint_p (bitset dst, bitset src)
428{
429 BITSET_CHECK2_ (dst, src);
430 return BITSET_DISJOINT_P_ (dst->s.bset, src->s.bset);
431}
432
433
434static bool
435bitset_stats_equal_p (bitset dst, bitset src)
436{
437 BITSET_CHECK2_ (dst, src);
438 return BITSET_EQUAL_P_ (dst->s.bset, src->s.bset);
439}
440
441
442static void
443bitset_stats_not (bitset dst, bitset src)
444{
445 BITSET_CHECK2_ (dst, src);
446 BITSET_NOT_ (dst->s.bset, src->s.bset);
447}
448
449
450static bool
451bitset_stats_subset_p (bitset dst, bitset src)
452{
453 BITSET_CHECK2_ (dst, src);
454 return BITSET_SUBSET_P_ (dst->s.bset, src->s.bset);
455}
456
457
458static void
459bitset_stats_and (bitset dst, bitset src1, bitset src2)
460{
461 BITSET_CHECK3_ (dst, src1, src2);
462 BITSET_AND_ (dst->s.bset, src1->s.bset, src2->s.bset);
463}
464
465
466static bool
467bitset_stats_and_cmp (bitset dst, bitset src1, bitset src2)
468{
469 BITSET_CHECK3_ (dst, src1, src2);
470 return BITSET_AND_CMP_ (dst->s.bset, src1->s.bset, src2->s.bset);
471}
472
473
474static void
475bitset_stats_andn (bitset dst, bitset src1, bitset src2)
476{
477 BITSET_CHECK3_ (dst, src1, src2);
478 BITSET_ANDN_ (dst->s.bset, src1->s.bset, src2->s.bset);
479}
480
481
482static bool
483bitset_stats_andn_cmp (bitset dst, bitset src1, bitset src2)
484{
485 BITSET_CHECK3_ (dst, src1, src2);
486 return BITSET_ANDN_CMP_ (dst->s.bset, src1->s.bset, src2->s.bset);
487}
488
489
490static void
491bitset_stats_or (bitset dst, bitset src1, bitset src2)
492{
493 BITSET_CHECK3_ (dst, src1, src2);
494 BITSET_OR_ (dst->s.bset, src1->s.bset, src2->s.bset);
495}
496
497
498static bool
499bitset_stats_or_cmp (bitset dst, bitset src1, bitset src2)
500{
501 BITSET_CHECK3_ (dst, src1, src2);
502 return BITSET_OR_CMP_ (dst->s.bset, src1->s.bset, src2->s.bset);
503}
504
505
506static void
507bitset_stats_xor (bitset dst, bitset src1, bitset src2)
508{
509 BITSET_CHECK3_ (dst, src1, src2);
510 BITSET_XOR_ (dst->s.bset, src1->s.bset, src2->s.bset);
511}
512
513
514static bool
515bitset_stats_xor_cmp (bitset dst, bitset src1, bitset src2)
516{
517 BITSET_CHECK3_ (dst, src1, src2);
518 return BITSET_XOR_CMP_ (dst->s.bset, src1->s.bset, src2->s.bset);
519}
520
521
522static void
523bitset_stats_and_or (bitset dst, bitset src1, bitset src2, bitset src3)
524{
525 BITSET_CHECK4_ (dst, src1, src2, src3);
526 BITSET_AND_OR_ (dst->s.bset, src1->s.bset, src2->s.bset, src3->s.bset);
527}
528
529
530static bool
531bitset_stats_and_or_cmp (bitset dst, bitset src1, bitset src2, bitset src3)
532{
533 BITSET_CHECK4_ (dst, src1, src2, src3);
534 return BITSET_AND_OR_CMP_ (dst->s.bset, src1->s.bset, src2->s.bset, src3->s.bset);
535}
536
537
538static void
539bitset_stats_andn_or (bitset dst, bitset src1, bitset src2, bitset src3)
540{
541 BITSET_CHECK4_ (dst, src1, src2, src3);
542 BITSET_ANDN_OR_ (dst->s.bset, src1->s.bset, src2->s.bset, src3->s.bset);
543}
544
545
546static bool
547bitset_stats_andn_or_cmp (bitset dst, bitset src1, bitset src2, bitset src3)
548{
549 BITSET_CHECK4_ (dst, src1, src2, src3);
550 return BITSET_ANDN_OR_CMP_ (dst->s.bset, src1->s.bset, src2->s.bset, src3->s.bset);
551}
552
553
554static void
555bitset_stats_or_and (bitset dst, bitset src1, bitset src2, bitset src3)
556{
557 BITSET_CHECK4_ (dst, src1, src2, src3);
558 BITSET_OR_AND_ (dst->s.bset, src1->s.bset, src2->s.bset, src3->s.bset);
559}
560
561
562static bool
563bitset_stats_or_and_cmp (bitset dst, bitset src1, bitset src2, bitset src3)
564{
565 BITSET_CHECK4_ (dst, src1, src2, src3);
566 return BITSET_OR_AND_CMP_ (dst->s.bset, src1->s.bset, src2->s.bset, src3->s.bset);
567}
568
569
570static bitset_bindex
571bitset_stats_list (bitset bset, bitset_bindex *list,
572 bitset_bindex num, bitset_bindex *next)
573{
574 bitset_bindex count;
575 bitset_bindex tmp;
576 bitset_bindex size;
577 bitset_bindex i;
578 enum bitset_type type;
579
580 count = BITSET_LIST_ (bset->s.bset, list, num, next);
581
582 type = BITSET_TYPE_ (bset->s.bset);
583 BITSET_STATS_LISTS_INC (bset->s.bset);
584
585 /* Log histogram of number of set bits. */
586 for (i = 0, tmp = count; tmp; tmp >>= 1, i++)
587 continue;
588 if (i >= BITSET_LOG_COUNT_BINS)
589 i = BITSET_LOG_COUNT_BINS - 1;
590 BITSET_STATS_LIST_COUNTS_INC (bset->s.bset, i);
591
592 /* Log histogram of number of bits in set. */
593 size = BITSET_SIZE_ (bset->s.bset);
594 for (i = 0, tmp = size; tmp; tmp >>= 1, i++)
595 continue;
596 if (i >= BITSET_LOG_SIZE_BINS)
597 i = BITSET_LOG_SIZE_BINS - 1;
598 BITSET_STATS_LIST_SIZES_INC (bset->s.bset, i);
599
600 /* Histogram of fraction of bits set. */
601 i = size ? (count * BITSET_DENSITY_BINS) / size : 0;
602 if (i >= BITSET_DENSITY_BINS)
603 i = BITSET_DENSITY_BINS - 1;
604 BITSET_STATS_LIST_DENSITY_INC (bset->s.bset, i);
605 return count;
606}
607
608
609static bitset_bindex
610bitset_stats_list_reverse (bitset bset, bitset_bindex *list,
611 bitset_bindex num, bitset_bindex *next)
612{
613 return BITSET_LIST_REVERSE_ (bset->s.bset, list, num, next);
614}
615
616
617static void
618bitset_stats_free (bitset bset)
619{
620 BITSET_STATS_FREES_INC (bset->s.bset);
621 BITSET_FREE_ (bset->s.bset);
622}
623
624
625struct bitset_vtable bitset_stats_vtable = {
626 bitset_stats_set,
627 bitset_stats_reset,
628 bitset_stats_toggle,
629 bitset_stats_test,
630 bitset_stats_resize,
631 bitset_stats_size,
632 bitset_stats_count,
633 bitset_stats_empty_p,
634 bitset_stats_ones,
635 bitset_stats_zero,
636 bitset_stats_copy,
637 bitset_stats_disjoint_p,
638 bitset_stats_equal_p,
639 bitset_stats_not,
640 bitset_stats_subset_p,
641 bitset_stats_and,
642 bitset_stats_and_cmp,
643 bitset_stats_andn,
644 bitset_stats_andn_cmp,
645 bitset_stats_or,
646 bitset_stats_or_cmp,
647 bitset_stats_xor,
648 bitset_stats_xor_cmp,
649 bitset_stats_and_or,
650 bitset_stats_and_or_cmp,
651 bitset_stats_andn_or,
652 bitset_stats_andn_or_cmp,
653 bitset_stats_or_and,
654 bitset_stats_or_and_cmp,
655 bitset_stats_list,
656 bitset_stats_list_reverse,
657 bitset_stats_free,
658 BITSET_STATS
659};
660
661
662/* Return enclosed bitset type. */
663enum bitset_type
664bitset_stats_type_get (bitset bset)
665{
666 return BITSET_TYPE_ (bset->s.bset);
667}
668
669
670size_t
671bitset_stats_bytes (void)
672{
673 return sizeof (struct bitset_stats_struct);
674}
675
676
677bitset
678bitset_stats_init (bitset bset, bitset_bindex n_bits, enum bitset_type type)
679{
680 size_t bytes;
681 bitset sbset;
682
683 bset->b.vtable = &bitset_stats_vtable;
684
685 /* Disable cache. */
686 bset->b.cindex = 0;
687 bset->b.csize = 0;
688 bset->b.cdata = 0;
689
690 BITSET_NBITS_ (bset) = n_bits;
691
692 /* Set up the actual bitset implementation that
693 we are a wrapper over. */
694 switch (type)
695 {
696 default:
697 abort ();
698
699 case BITSET_ARRAY:
700 bytes = abitset_bytes (n_bits);
701 sbset = xcalloc (1, bytes);
702 abitset_init (sbset, n_bits);
703 break;
704
705 case BITSET_LIST:
706 bytes = lbitset_bytes (n_bits);
707 sbset = xcalloc (1, bytes);
708 lbitset_init (sbset, n_bits);
709 break;
710
711 case BITSET_TABLE:
712 bytes = ebitset_bytes (n_bits);
713 sbset = xcalloc (1, bytes);
714 ebitset_init (sbset, n_bits);
715 break;
716
717 case BITSET_VARRAY:
718 bytes = vbitset_bytes (n_bits);
719 sbset = xcalloc (1, bytes);
720 vbitset_init (sbset, n_bits);
721 break;
722 }
723
724 bset->s.bset = sbset;
725
726 BITSET_STATS_ALLOCS_INC (type);
727
728 return bset;
729}