2 Copyright (C) 2002-2006, 2009-2010 Free Software Foundation, Inc.
3 Contributed by Michael Hayes (m.hayes@elec.canterbury.ac.nz).
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 3 of the License, or
8 (at your option) any later version.
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.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>. */
18 /* This file is a wrapper bitset implementation for the other bitset
19 implementations. It provides bitset compatibility checking and
20 statistics gathering without having to instrument the bitset
21 implementations. When statistics gathering is enabled, the bitset
22 operations get vectored through here and we then call the appropriate
27 #include "bitset_stats.h"
39 #define _(Msgid) gettext (Msgid)
41 /* Configuration macros. */
42 #define BITSET_STATS_FILE "bitset.dat"
43 #define BITSET_LOG_COUNT_BINS 10
44 #define BITSET_LOG_SIZE_BINS 16
45 #define BITSET_DENSITY_BINS 20
48 /* Accessor macros. */
49 #define BITSET_STATS_ALLOCS_INC(TYPE) \
50 bitset_stats_info->types[(TYPE)].allocs++
51 #define BITSET_STATS_FREES_INC(BSET) \
52 bitset_stats_info->types[BITSET_TYPE_ (BSET)].frees++
53 #define BITSET_STATS_SETS_INC(BSET) \
54 bitset_stats_info->types[BITSET_TYPE_ (BSET)].sets++
55 #define BITSET_STATS_CACHE_SETS_INC(BSET) \
56 bitset_stats_info->types[BITSET_TYPE_ (BSET)].cache_sets++
57 #define BITSET_STATS_RESETS_INC(BSET) \
58 bitset_stats_info->types[BITSET_TYPE_ (BSET)].resets++
59 #define BITSET_STATS_CACHE_RESETS_INC(BSET) \
60 bitset_stats_info->types[BITSET_TYPE_ (BSET)].cache_resets++
61 #define BITSET_STATS_TESTS_INC(BSET) \
62 bitset_stats_info->types[BITSET_TYPE_ (BSET)].tests++
63 #define BITSET_STATS_CACHE_TESTS_INC(BSET) \
64 bitset_stats_info->types[BITSET_TYPE_ (BSET)].cache_tests++
65 #define BITSET_STATS_LISTS_INC(BSET) \
66 bitset_stats_info->types[BITSET_TYPE_ (BSET)].lists++
67 #define BITSET_STATS_LIST_COUNTS_INC(BSET, I) \
68 bitset_stats_info->types[BITSET_TYPE_ (BSET)].list_counts[(I)]++
69 #define BITSET_STATS_LIST_SIZES_INC(BSET, I) \
70 bitset_stats_info->types[BITSET_TYPE_ (BSET)].list_sizes[(I)]++
71 #define BITSET_STATS_LIST_DENSITY_INC(BSET, I) \
72 bitset_stats_info->types[BITSET_TYPE_ (BSET)].list_density[(I)]++
75 struct bitset_type_info_struct
81 unsigned int cache_sets
;
83 unsigned int cache_resets
;
85 unsigned int cache_tests
;
86 unsigned int list_counts
[BITSET_LOG_COUNT_BINS
];
87 unsigned int list_sizes
[BITSET_LOG_SIZE_BINS
];
88 unsigned int list_density
[BITSET_DENSITY_BINS
];
91 struct bitset_stats_info_struct
94 struct bitset_type_info_struct types
[BITSET_TYPE_NUM
];
98 struct bitset_stats_info_struct bitset_stats_info_data
;
99 struct bitset_stats_info_struct
*bitset_stats_info
;
100 bool bitset_stats_enabled
= false;
103 /* Print a percentage histogram with message MSG to FILE. */
105 bitset_percent_histogram_print (FILE *file
, const char *name
, const char *msg
,
106 unsigned int n_bins
, unsigned int *bins
)
112 for (i
= 0; i
< n_bins
; i
++)
118 fprintf (file
, "%s %s", name
, msg
);
119 for (i
= 0; i
< n_bins
; i
++)
120 fprintf (file
, "%.0f-%.0f%%\t%8u (%5.1f%%)\n",
122 (i
+ 1) * 100.0 / n_bins
, bins
[i
],
123 (100.0 * bins
[i
]) / total
);
127 /* Print a log histogram with message MSG to FILE. */
129 bitset_log_histogram_print (FILE *file
, const char *name
, const char *msg
,
130 unsigned int n_bins
, unsigned int *bins
)
134 unsigned int max_width
;
137 for (i
= 0; i
< n_bins
; i
++)
143 /* Determine number of useful bins. */
144 for (i
= n_bins
; i
> 3 && ! bins
[i
- 1]; i
--)
148 /* 2 * ceil (log10 (2) * (N - 1)) + 1. */
149 max_width
= 2 * (unsigned int) (0.30103 * (n_bins
- 1) + 0.9999) + 1;
151 fprintf (file
, "%s %s", name
, msg
);
152 for (i
= 0; i
< 2; i
++)
153 fprintf (file
, "%*d\t%8u (%5.1f%%)\n",
154 max_width
, i
, bins
[i
], 100.0 * bins
[i
] / total
);
156 for (; i
< n_bins
; i
++)
157 fprintf (file
, "%*lu-%lu\t%8u (%5.1f%%)\n",
158 max_width
- ((unsigned int) (0.30103 * (i
) + 0.9999) + 1),
162 (100.0 * bins
[i
]) / total
);
166 /* Print bitset statistics to FILE. */
168 bitset_stats_print_1 (FILE *file
, const char *name
,
169 struct bitset_type_info_struct
*stats
)
174 fprintf (file
, "%s:\n", name
);
175 fprintf (file
, _("%u bitset_allocs, %u freed (%.2f%%).\n"),
176 stats
->allocs
, stats
->frees
,
177 stats
->allocs
? 100.0 * stats
->frees
/ stats
->allocs
: 0);
178 fprintf (file
, _("%u bitset_sets, %u cached (%.2f%%)\n"),
179 stats
->sets
, stats
->cache_sets
,
180 stats
->sets
? 100.0 * stats
->cache_sets
/ stats
->sets
: 0);
181 fprintf (file
, _("%u bitset_resets, %u cached (%.2f%%)\n"),
182 stats
->resets
, stats
->cache_resets
,
183 stats
->resets
? 100.0 * stats
->cache_resets
/ stats
->resets
: 0);
184 fprintf (file
, _("%u bitset_tests, %u cached (%.2f%%)\n"),
185 stats
->tests
, stats
->cache_tests
,
186 stats
->tests
? 100.0 * stats
->cache_tests
/ stats
->tests
: 0);
188 fprintf (file
, _("%u bitset_lists\n"), stats
->lists
);
190 bitset_log_histogram_print (file
, name
, _("count log histogram\n"),
191 BITSET_LOG_COUNT_BINS
, stats
->list_counts
);
193 bitset_log_histogram_print (file
, name
, _("size log histogram\n"),
194 BITSET_LOG_SIZE_BINS
, stats
->list_sizes
);
196 bitset_percent_histogram_print (file
, name
, _("density histogram\n"),
197 BITSET_DENSITY_BINS
, stats
->list_density
);
201 /* Print all bitset statistics to FILE. */
203 bitset_stats_print (FILE *file
, bool verbose ATTRIBUTE_UNUSED
)
207 if (!bitset_stats_info
)
210 fprintf (file
, _("Bitset statistics:\n\n"));
212 if (bitset_stats_info
->runs
> 1)
213 fprintf (file
, _("Accumulated runs = %u\n"), bitset_stats_info
->runs
);
215 for (i
= 0; i
< BITSET_TYPE_NUM
; i
++)
216 bitset_stats_print_1 (file
, bitset_type_names
[i
],
217 &bitset_stats_info
->types
[i
]);
221 /* Initialise bitset statistics logging. */
223 bitset_stats_enable (void)
225 if (!bitset_stats_info
)
226 bitset_stats_info
= &bitset_stats_info_data
;
227 bitset_stats_enabled
= true;
232 bitset_stats_disable (void)
234 bitset_stats_enabled
= false;
238 /* Read bitset statistics file. */
240 bitset_stats_read (const char *file_name
)
244 if (!bitset_stats_info
)
248 file_name
= BITSET_STATS_FILE
;
250 file
= fopen (file_name
, "r");
253 if (fread (&bitset_stats_info_data
, sizeof (bitset_stats_info_data
),
257 perror (_("Could not read stats file."));
259 fprintf (stderr
, _("Bad stats file size.\n"));
261 if (fclose (file
) != 0)
262 perror (_("Could not read stats file."));
264 bitset_stats_info_data
.runs
++;
268 /* Write bitset statistics file. */
270 bitset_stats_write (const char *file_name
)
274 if (!bitset_stats_info
)
278 file_name
= BITSET_STATS_FILE
;
280 file
= fopen (file_name
, "w");
283 if (fwrite (&bitset_stats_info_data
, sizeof (bitset_stats_info_data
),
285 perror (_("Could not write stats file."));
286 if (fclose (file
) != 0)
287 perror (_("Could not write stats file."));
290 perror (_("Could not open stats file for writing."));
294 /* Dump bitset statistics to FILE. */
296 bitset_stats_dump (FILE *file
)
298 bitset_stats_print (file
, false);
302 /* Function to be called from debugger to print bitset stats. */
304 debug_bitset_stats (void)
306 bitset_stats_print (stderr
, true);
311 bitset_stats_set (bitset dst
, bitset_bindex bitno
)
313 bitset bset
= dst
->s
.bset
;
314 bitset_windex wordno
= bitno
/ BITSET_WORD_BITS
;
315 bitset_windex offset
= wordno
- bset
->b
.cindex
;
317 BITSET_STATS_SETS_INC (bset
);
319 if (offset
< bset
->b
.csize
)
321 bset
->b
.cdata
[offset
] |= (bitset_word
) 1 << (bitno
% BITSET_WORD_BITS
);
322 BITSET_STATS_CACHE_SETS_INC (bset
);
325 BITSET_SET_ (bset
, bitno
);
330 bitset_stats_reset (bitset dst
, bitset_bindex bitno
)
332 bitset bset
= dst
->s
.bset
;
333 bitset_windex wordno
= bitno
/ BITSET_WORD_BITS
;
334 bitset_windex offset
= wordno
- bset
->b
.cindex
;
336 BITSET_STATS_RESETS_INC (bset
);
338 if (offset
< bset
->b
.csize
)
340 bset
->b
.cdata
[offset
] &=
341 ~((bitset_word
) 1 << (bitno
% BITSET_WORD_BITS
));
342 BITSET_STATS_CACHE_RESETS_INC (bset
);
345 BITSET_RESET_ (bset
, bitno
);
350 bitset_stats_toggle (bitset src
, bitset_bindex bitno
)
352 return BITSET_TOGGLE_ (src
->s
.bset
, bitno
);
357 bitset_stats_test (bitset src
, bitset_bindex bitno
)
359 bitset bset
= src
->s
.bset
;
360 bitset_windex wordno
= bitno
/ BITSET_WORD_BITS
;
361 bitset_windex offset
= wordno
- bset
->b
.cindex
;
363 BITSET_STATS_TESTS_INC (bset
);
365 if (offset
< bset
->b
.csize
)
367 BITSET_STATS_CACHE_TESTS_INC (bset
);
368 return (bset
->b
.cdata
[offset
] >> (bitno
% BITSET_WORD_BITS
)) & 1;
371 return BITSET_TEST_ (bset
, bitno
);
376 bitset_stats_resize (bitset src
, bitset_bindex size
)
378 return BITSET_RESIZE_ (src
->s
.bset
, size
);
383 bitset_stats_size (bitset src
)
385 return BITSET_SIZE_ (src
->s
.bset
);
390 bitset_stats_count (bitset src
)
392 return BITSET_COUNT_ (src
->s
.bset
);
397 bitset_stats_empty_p (bitset dst
)
399 return BITSET_EMPTY_P_ (dst
->s
.bset
);
404 bitset_stats_ones (bitset dst
)
406 BITSET_ONES_ (dst
->s
.bset
);
411 bitset_stats_zero (bitset dst
)
413 BITSET_ZERO_ (dst
->s
.bset
);
418 bitset_stats_copy (bitset dst
, bitset src
)
420 BITSET_CHECK2_ (dst
, src
);
421 BITSET_COPY_ (dst
->s
.bset
, src
->s
.bset
);
426 bitset_stats_disjoint_p (bitset dst
, bitset src
)
428 BITSET_CHECK2_ (dst
, src
);
429 return BITSET_DISJOINT_P_ (dst
->s
.bset
, src
->s
.bset
);
434 bitset_stats_equal_p (bitset dst
, bitset src
)
436 BITSET_CHECK2_ (dst
, src
);
437 return BITSET_EQUAL_P_ (dst
->s
.bset
, src
->s
.bset
);
442 bitset_stats_not (bitset dst
, bitset src
)
444 BITSET_CHECK2_ (dst
, src
);
445 BITSET_NOT_ (dst
->s
.bset
, src
->s
.bset
);
450 bitset_stats_subset_p (bitset dst
, bitset src
)
452 BITSET_CHECK2_ (dst
, src
);
453 return BITSET_SUBSET_P_ (dst
->s
.bset
, src
->s
.bset
);
458 bitset_stats_and (bitset dst
, bitset src1
, bitset src2
)
460 BITSET_CHECK3_ (dst
, src1
, src2
);
461 BITSET_AND_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
);
466 bitset_stats_and_cmp (bitset dst
, bitset src1
, bitset src2
)
468 BITSET_CHECK3_ (dst
, src1
, src2
);
469 return BITSET_AND_CMP_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
);
474 bitset_stats_andn (bitset dst
, bitset src1
, bitset src2
)
476 BITSET_CHECK3_ (dst
, src1
, src2
);
477 BITSET_ANDN_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
);
482 bitset_stats_andn_cmp (bitset dst
, bitset src1
, bitset src2
)
484 BITSET_CHECK3_ (dst
, src1
, src2
);
485 return BITSET_ANDN_CMP_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
);
490 bitset_stats_or (bitset dst
, bitset src1
, bitset src2
)
492 BITSET_CHECK3_ (dst
, src1
, src2
);
493 BITSET_OR_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
);
498 bitset_stats_or_cmp (bitset dst
, bitset src1
, bitset src2
)
500 BITSET_CHECK3_ (dst
, src1
, src2
);
501 return BITSET_OR_CMP_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
);
506 bitset_stats_xor (bitset dst
, bitset src1
, bitset src2
)
508 BITSET_CHECK3_ (dst
, src1
, src2
);
509 BITSET_XOR_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
);
514 bitset_stats_xor_cmp (bitset dst
, bitset src1
, bitset src2
)
516 BITSET_CHECK3_ (dst
, src1
, src2
);
517 return BITSET_XOR_CMP_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
);
522 bitset_stats_and_or (bitset dst
, bitset src1
, bitset src2
, bitset src3
)
524 BITSET_CHECK4_ (dst
, src1
, src2
, src3
);
525 BITSET_AND_OR_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
, src3
->s
.bset
);
530 bitset_stats_and_or_cmp (bitset dst
, bitset src1
, bitset src2
, bitset src3
)
532 BITSET_CHECK4_ (dst
, src1
, src2
, src3
);
533 return BITSET_AND_OR_CMP_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
, src3
->s
.bset
);
538 bitset_stats_andn_or (bitset dst
, bitset src1
, bitset src2
, bitset src3
)
540 BITSET_CHECK4_ (dst
, src1
, src2
, src3
);
541 BITSET_ANDN_OR_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
, src3
->s
.bset
);
546 bitset_stats_andn_or_cmp (bitset dst
, bitset src1
, bitset src2
, bitset src3
)
548 BITSET_CHECK4_ (dst
, src1
, src2
, src3
);
549 return BITSET_ANDN_OR_CMP_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
, src3
->s
.bset
);
554 bitset_stats_or_and (bitset dst
, bitset src1
, bitset src2
, bitset src3
)
556 BITSET_CHECK4_ (dst
, src1
, src2
, src3
);
557 BITSET_OR_AND_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
, src3
->s
.bset
);
562 bitset_stats_or_and_cmp (bitset dst
, bitset src1
, bitset src2
, bitset src3
)
564 BITSET_CHECK4_ (dst
, src1
, src2
, src3
);
565 return BITSET_OR_AND_CMP_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
, src3
->s
.bset
);
570 bitset_stats_list (bitset bset
, bitset_bindex
*list
,
571 bitset_bindex num
, bitset_bindex
*next
)
577 enum bitset_type type
;
579 count
= BITSET_LIST_ (bset
->s
.bset
, list
, num
, next
);
581 type
= BITSET_TYPE_ (bset
->s
.bset
);
582 BITSET_STATS_LISTS_INC (bset
->s
.bset
);
584 /* Log histogram of number of set bits. */
585 for (i
= 0, tmp
= count
; tmp
; tmp
>>= 1, i
++)
587 if (i
>= BITSET_LOG_COUNT_BINS
)
588 i
= BITSET_LOG_COUNT_BINS
- 1;
589 BITSET_STATS_LIST_COUNTS_INC (bset
->s
.bset
, i
);
591 /* Log histogram of number of bits in set. */
592 size
= BITSET_SIZE_ (bset
->s
.bset
);
593 for (i
= 0, tmp
= size
; tmp
; tmp
>>= 1, i
++)
595 if (i
>= BITSET_LOG_SIZE_BINS
)
596 i
= BITSET_LOG_SIZE_BINS
- 1;
597 BITSET_STATS_LIST_SIZES_INC (bset
->s
.bset
, i
);
599 /* Histogram of fraction of bits set. */
600 i
= size
? (count
* BITSET_DENSITY_BINS
) / size
: 0;
601 if (i
>= BITSET_DENSITY_BINS
)
602 i
= BITSET_DENSITY_BINS
- 1;
603 BITSET_STATS_LIST_DENSITY_INC (bset
->s
.bset
, i
);
609 bitset_stats_list_reverse (bitset bset
, bitset_bindex
*list
,
610 bitset_bindex num
, bitset_bindex
*next
)
612 return BITSET_LIST_REVERSE_ (bset
->s
.bset
, list
, num
, next
);
617 bitset_stats_free (bitset bset
)
619 BITSET_STATS_FREES_INC (bset
->s
.bset
);
620 BITSET_FREE_ (bset
->s
.bset
);
624 struct bitset_vtable bitset_stats_vtable
= {
632 bitset_stats_empty_p
,
636 bitset_stats_disjoint_p
,
637 bitset_stats_equal_p
,
639 bitset_stats_subset_p
,
641 bitset_stats_and_cmp
,
643 bitset_stats_andn_cmp
,
647 bitset_stats_xor_cmp
,
649 bitset_stats_and_or_cmp
,
650 bitset_stats_andn_or
,
651 bitset_stats_andn_or_cmp
,
653 bitset_stats_or_and_cmp
,
655 bitset_stats_list_reverse
,
661 /* Return enclosed bitset type. */
663 bitset_stats_type_get (bitset bset
)
665 return BITSET_TYPE_ (bset
->s
.bset
);
670 bitset_stats_bytes (void)
672 return sizeof (struct bitset_stats_struct
);
677 bitset_stats_init (bitset bset
, bitset_bindex n_bits
, enum bitset_type type
)
682 bset
->b
.vtable
= &bitset_stats_vtable
;
689 BITSET_NBITS_ (bset
) = n_bits
;
691 /* Set up the actual bitset implementation that
692 we are a wrapper over. */
699 bytes
= abitset_bytes (n_bits
);
700 sbset
= xcalloc (1, bytes
);
701 abitset_init (sbset
, n_bits
);
705 bytes
= lbitset_bytes (n_bits
);
706 sbset
= xcalloc (1, bytes
);
707 lbitset_init (sbset
, n_bits
);
711 bytes
= ebitset_bytes (n_bits
);
712 sbset
= xcalloc (1, bytes
);
713 ebitset_init (sbset
, n_bits
);
717 bytes
= vbitset_bytes (n_bits
);
718 sbset
= xcalloc (1, bytes
);
719 vbitset_init (sbset
, n_bits
);
723 bset
->s
.bset
= sbset
;
725 BITSET_STATS_ALLOCS_INC (type
);