3 Copyright (C) 2002, 2003, 2004, 2005, 2006, 2009, 2010 Free
4 Software Foundation, Inc.
6 Contributed by Michael Hayes (m.hayes@elec.canterbury.ac.nz).
8 This program is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
21 /* This file is a wrapper bitset implementation for the other bitset
22 implementations. It provides bitset compatibility checking and
23 statistics gathering without having to instrument the bitset
24 implementations. When statistics gathering is enabled, the bitset
25 operations get vectored through here and we then call the appropriate
30 #include "bitset_stats.h"
42 #define _(Msgid) gettext (Msgid)
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
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)]++
78 struct bitset_type_info_struct
84 unsigned int cache_sets
;
86 unsigned int cache_resets
;
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
];
94 struct bitset_stats_info_struct
97 struct bitset_type_info_struct types
[BITSET_TYPE_NUM
];
101 struct bitset_stats_info_struct bitset_stats_info_data
;
102 struct bitset_stats_info_struct
*bitset_stats_info
;
103 bool bitset_stats_enabled
= false;
106 /* Print a percentage histogram with message MSG to FILE. */
108 bitset_percent_histogram_print (FILE *file
, const char *name
, const char *msg
,
109 unsigned int n_bins
, unsigned int *bins
)
115 for (i
= 0; i
< n_bins
; i
++)
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",
125 (i
+ 1) * 100.0 / n_bins
, bins
[i
],
126 (100.0 * bins
[i
]) / total
);
130 /* Print a log histogram with message MSG to FILE. */
132 bitset_log_histogram_print (FILE *file
, const char *name
, const char *msg
,
133 unsigned int n_bins
, unsigned int *bins
)
137 unsigned int max_width
;
140 for (i
= 0; i
< n_bins
; i
++)
146 /* Determine number of useful bins. */
147 for (i
= n_bins
; i
> 3 && ! bins
[i
- 1]; i
--)
151 /* 2 * ceil (log10 (2) * (N - 1)) + 1. */
152 max_width
= 2 * (unsigned int) (0.30103 * (n_bins
- 1) + 0.9999) + 1;
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
);
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),
165 (100.0 * bins
[i
]) / total
);
169 /* Print bitset statistics to FILE. */
171 bitset_stats_print_1 (FILE *file
, const char *name
,
172 struct bitset_type_info_struct
*stats
)
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);
191 fprintf (file
, _("%u bitset_lists\n"), stats
->lists
);
193 bitset_log_histogram_print (file
, name
, _("count log histogram\n"),
194 BITSET_LOG_COUNT_BINS
, stats
->list_counts
);
196 bitset_log_histogram_print (file
, name
, _("size log histogram\n"),
197 BITSET_LOG_SIZE_BINS
, stats
->list_sizes
);
199 bitset_percent_histogram_print (file
, name
, _("density histogram\n"),
200 BITSET_DENSITY_BINS
, stats
->list_density
);
204 /* Print all bitset statistics to FILE. */
206 bitset_stats_print (FILE *file
, bool verbose ATTRIBUTE_UNUSED
)
210 if (!bitset_stats_info
)
213 fprintf (file
, _("Bitset statistics:\n\n"));
215 if (bitset_stats_info
->runs
> 1)
216 fprintf (file
, _("Accumulated runs = %u\n"), bitset_stats_info
->runs
);
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
]);
224 /* Initialise bitset statistics logging. */
226 bitset_stats_enable (void)
228 if (!bitset_stats_info
)
229 bitset_stats_info
= &bitset_stats_info_data
;
230 bitset_stats_enabled
= true;
235 bitset_stats_disable (void)
237 bitset_stats_enabled
= false;
241 /* Read bitset statistics file. */
243 bitset_stats_read (const char *file_name
)
247 if (!bitset_stats_info
)
251 file_name
= BITSET_STATS_FILE
;
253 file
= fopen (file_name
, "r");
256 if (fread (&bitset_stats_info_data
, sizeof (bitset_stats_info_data
),
260 perror (_("Could not read stats file."));
262 fprintf (stderr
, _("Bad stats file size.\n"));
264 if (fclose (file
) != 0)
265 perror (_("Could not read stats file."));
267 bitset_stats_info_data
.runs
++;
271 /* Write bitset statistics file. */
273 bitset_stats_write (const char *file_name
)
277 if (!bitset_stats_info
)
281 file_name
= BITSET_STATS_FILE
;
283 file
= fopen (file_name
, "w");
286 if (fwrite (&bitset_stats_info_data
, sizeof (bitset_stats_info_data
),
288 perror (_("Could not write stats file."));
289 if (fclose (file
) != 0)
290 perror (_("Could not write stats file."));
293 perror (_("Could not open stats file for writing."));
297 /* Dump bitset statistics to FILE. */
299 bitset_stats_dump (FILE *file
)
301 bitset_stats_print (file
, false);
305 /* Function to be called from debugger to print bitset stats. */
307 debug_bitset_stats (void)
309 bitset_stats_print (stderr
, true);
314 bitset_stats_set (bitset dst
, bitset_bindex bitno
)
316 bitset bset
= dst
->s
.bset
;
317 bitset_windex wordno
= bitno
/ BITSET_WORD_BITS
;
318 bitset_windex offset
= wordno
- bset
->b
.cindex
;
320 BITSET_STATS_SETS_INC (bset
);
322 if (offset
< bset
->b
.csize
)
324 bset
->b
.cdata
[offset
] |= (bitset_word
) 1 << (bitno
% BITSET_WORD_BITS
);
325 BITSET_STATS_CACHE_SETS_INC (bset
);
328 BITSET_SET_ (bset
, bitno
);
333 bitset_stats_reset (bitset dst
, bitset_bindex bitno
)
335 bitset bset
= dst
->s
.bset
;
336 bitset_windex wordno
= bitno
/ BITSET_WORD_BITS
;
337 bitset_windex offset
= wordno
- bset
->b
.cindex
;
339 BITSET_STATS_RESETS_INC (bset
);
341 if (offset
< bset
->b
.csize
)
343 bset
->b
.cdata
[offset
] &=
344 ~((bitset_word
) 1 << (bitno
% BITSET_WORD_BITS
));
345 BITSET_STATS_CACHE_RESETS_INC (bset
);
348 BITSET_RESET_ (bset
, bitno
);
353 bitset_stats_toggle (bitset src
, bitset_bindex bitno
)
355 return BITSET_TOGGLE_ (src
->s
.bset
, bitno
);
360 bitset_stats_test (bitset src
, bitset_bindex bitno
)
362 bitset bset
= src
->s
.bset
;
363 bitset_windex wordno
= bitno
/ BITSET_WORD_BITS
;
364 bitset_windex offset
= wordno
- bset
->b
.cindex
;
366 BITSET_STATS_TESTS_INC (bset
);
368 if (offset
< bset
->b
.csize
)
370 BITSET_STATS_CACHE_TESTS_INC (bset
);
371 return (bset
->b
.cdata
[offset
] >> (bitno
% BITSET_WORD_BITS
)) & 1;
374 return BITSET_TEST_ (bset
, bitno
);
379 bitset_stats_resize (bitset src
, bitset_bindex size
)
381 return BITSET_RESIZE_ (src
->s
.bset
, size
);
386 bitset_stats_size (bitset src
)
388 return BITSET_SIZE_ (src
->s
.bset
);
393 bitset_stats_count (bitset src
)
395 return BITSET_COUNT_ (src
->s
.bset
);
400 bitset_stats_empty_p (bitset dst
)
402 return BITSET_EMPTY_P_ (dst
->s
.bset
);
407 bitset_stats_ones (bitset dst
)
409 BITSET_ONES_ (dst
->s
.bset
);
414 bitset_stats_zero (bitset dst
)
416 BITSET_ZERO_ (dst
->s
.bset
);
421 bitset_stats_copy (bitset dst
, bitset src
)
423 BITSET_CHECK2_ (dst
, src
);
424 BITSET_COPY_ (dst
->s
.bset
, src
->s
.bset
);
429 bitset_stats_disjoint_p (bitset dst
, bitset src
)
431 BITSET_CHECK2_ (dst
, src
);
432 return BITSET_DISJOINT_P_ (dst
->s
.bset
, src
->s
.bset
);
437 bitset_stats_equal_p (bitset dst
, bitset src
)
439 BITSET_CHECK2_ (dst
, src
);
440 return BITSET_EQUAL_P_ (dst
->s
.bset
, src
->s
.bset
);
445 bitset_stats_not (bitset dst
, bitset src
)
447 BITSET_CHECK2_ (dst
, src
);
448 BITSET_NOT_ (dst
->s
.bset
, src
->s
.bset
);
453 bitset_stats_subset_p (bitset dst
, bitset src
)
455 BITSET_CHECK2_ (dst
, src
);
456 return BITSET_SUBSET_P_ (dst
->s
.bset
, src
->s
.bset
);
461 bitset_stats_and (bitset dst
, bitset src1
, bitset src2
)
463 BITSET_CHECK3_ (dst
, src1
, src2
);
464 BITSET_AND_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
);
469 bitset_stats_and_cmp (bitset dst
, bitset src1
, bitset src2
)
471 BITSET_CHECK3_ (dst
, src1
, src2
);
472 return BITSET_AND_CMP_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
);
477 bitset_stats_andn (bitset dst
, bitset src1
, bitset src2
)
479 BITSET_CHECK3_ (dst
, src1
, src2
);
480 BITSET_ANDN_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
);
485 bitset_stats_andn_cmp (bitset dst
, bitset src1
, bitset src2
)
487 BITSET_CHECK3_ (dst
, src1
, src2
);
488 return BITSET_ANDN_CMP_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
);
493 bitset_stats_or (bitset dst
, bitset src1
, bitset src2
)
495 BITSET_CHECK3_ (dst
, src1
, src2
);
496 BITSET_OR_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
);
501 bitset_stats_or_cmp (bitset dst
, bitset src1
, bitset src2
)
503 BITSET_CHECK3_ (dst
, src1
, src2
);
504 return BITSET_OR_CMP_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
);
509 bitset_stats_xor (bitset dst
, bitset src1
, bitset src2
)
511 BITSET_CHECK3_ (dst
, src1
, src2
);
512 BITSET_XOR_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
);
517 bitset_stats_xor_cmp (bitset dst
, bitset src1
, bitset src2
)
519 BITSET_CHECK3_ (dst
, src1
, src2
);
520 return BITSET_XOR_CMP_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
);
525 bitset_stats_and_or (bitset dst
, bitset src1
, bitset src2
, bitset src3
)
527 BITSET_CHECK4_ (dst
, src1
, src2
, src3
);
528 BITSET_AND_OR_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
, src3
->s
.bset
);
533 bitset_stats_and_or_cmp (bitset dst
, bitset src1
, bitset src2
, bitset src3
)
535 BITSET_CHECK4_ (dst
, src1
, src2
, src3
);
536 return BITSET_AND_OR_CMP_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
, src3
->s
.bset
);
541 bitset_stats_andn_or (bitset dst
, bitset src1
, bitset src2
, bitset src3
)
543 BITSET_CHECK4_ (dst
, src1
, src2
, src3
);
544 BITSET_ANDN_OR_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
, src3
->s
.bset
);
549 bitset_stats_andn_or_cmp (bitset dst
, bitset src1
, bitset src2
, bitset src3
)
551 BITSET_CHECK4_ (dst
, src1
, src2
, src3
);
552 return BITSET_ANDN_OR_CMP_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
, src3
->s
.bset
);
557 bitset_stats_or_and (bitset dst
, bitset src1
, bitset src2
, bitset src3
)
559 BITSET_CHECK4_ (dst
, src1
, src2
, src3
);
560 BITSET_OR_AND_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
, src3
->s
.bset
);
565 bitset_stats_or_and_cmp (bitset dst
, bitset src1
, bitset src2
, bitset src3
)
567 BITSET_CHECK4_ (dst
, src1
, src2
, src3
);
568 return BITSET_OR_AND_CMP_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
, src3
->s
.bset
);
573 bitset_stats_list (bitset bset
, bitset_bindex
*list
,
574 bitset_bindex num
, bitset_bindex
*next
)
580 enum bitset_type type
;
582 count
= BITSET_LIST_ (bset
->s
.bset
, list
, num
, next
);
584 type
= BITSET_TYPE_ (bset
->s
.bset
);
585 BITSET_STATS_LISTS_INC (bset
->s
.bset
);
587 /* Log histogram of number of set bits. */
588 for (i
= 0, tmp
= count
; tmp
; tmp
>>= 1, i
++)
590 if (i
>= BITSET_LOG_COUNT_BINS
)
591 i
= BITSET_LOG_COUNT_BINS
- 1;
592 BITSET_STATS_LIST_COUNTS_INC (bset
->s
.bset
, i
);
594 /* Log histogram of number of bits in set. */
595 size
= BITSET_SIZE_ (bset
->s
.bset
);
596 for (i
= 0, tmp
= size
; tmp
; tmp
>>= 1, i
++)
598 if (i
>= BITSET_LOG_SIZE_BINS
)
599 i
= BITSET_LOG_SIZE_BINS
- 1;
600 BITSET_STATS_LIST_SIZES_INC (bset
->s
.bset
, i
);
602 /* Histogram of fraction of bits set. */
603 i
= size
? (count
* BITSET_DENSITY_BINS
) / size
: 0;
604 if (i
>= BITSET_DENSITY_BINS
)
605 i
= BITSET_DENSITY_BINS
- 1;
606 BITSET_STATS_LIST_DENSITY_INC (bset
->s
.bset
, i
);
612 bitset_stats_list_reverse (bitset bset
, bitset_bindex
*list
,
613 bitset_bindex num
, bitset_bindex
*next
)
615 return BITSET_LIST_REVERSE_ (bset
->s
.bset
, list
, num
, next
);
620 bitset_stats_free (bitset bset
)
622 BITSET_STATS_FREES_INC (bset
->s
.bset
);
623 BITSET_FREE_ (bset
->s
.bset
);
627 struct bitset_vtable bitset_stats_vtable
= {
635 bitset_stats_empty_p
,
639 bitset_stats_disjoint_p
,
640 bitset_stats_equal_p
,
642 bitset_stats_subset_p
,
644 bitset_stats_and_cmp
,
646 bitset_stats_andn_cmp
,
650 bitset_stats_xor_cmp
,
652 bitset_stats_and_or_cmp
,
653 bitset_stats_andn_or
,
654 bitset_stats_andn_or_cmp
,
656 bitset_stats_or_and_cmp
,
658 bitset_stats_list_reverse
,
664 /* Return enclosed bitset type. */
666 bitset_stats_type_get (bitset bset
)
668 return BITSET_TYPE_ (bset
->s
.bset
);
673 bitset_stats_bytes (void)
675 return sizeof (struct bitset_stats_struct
);
680 bitset_stats_init (bitset bset
, bitset_bindex n_bits
, enum bitset_type type
)
685 bset
->b
.vtable
= &bitset_stats_vtable
;
692 BITSET_NBITS_ (bset
) = n_bits
;
694 /* Set up the actual bitset implementation that
695 we are a wrapper over. */
702 bytes
= abitset_bytes (n_bits
);
703 sbset
= xcalloc (1, bytes
);
704 abitset_init (sbset
, n_bits
);
708 bytes
= lbitset_bytes (n_bits
);
709 sbset
= xcalloc (1, bytes
);
710 lbitset_init (sbset
, n_bits
);
714 bytes
= ebitset_bytes (n_bits
);
715 sbset
= xcalloc (1, bytes
);
716 ebitset_init (sbset
, n_bits
);
720 bytes
= vbitset_bytes (n_bits
);
721 sbset
= xcalloc (1, bytes
);
722 vbitset_init (sbset
, n_bits
);
726 bset
->s
.bset
= sbset
;
728 BITSET_STATS_ALLOCS_INC (type
);