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