2 Copyright (C) 2002 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 2 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, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
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
37 #include "bitset_stats.h"
44 #define _(Msgid) gettext (Msgid)
46 #define _(Msgid) Msgid
49 /* Configuration macros. */
50 #define BITSET_STATS_FILE "bitset.dat"
51 #define BITSET_LOG_COUNT_BINS 10
52 #define BITSET_LOG_SIZE_BINS 16
53 #define BITSET_DENSITY_BINS 20
56 /* Accessor macros. */
57 #define BITSET_STATS_ALLOCS_INC(TYPE) \
58 bitset_stats_info->types[(TYPE)].allocs++
59 #define BITSET_STATS_FREES_INC(BSET) \
60 bitset_stats_info->types[BITSET_TYPE_ (BSET)].frees++
61 #define BITSET_STATS_SETS_INC(BSET) \
62 bitset_stats_info->types[BITSET_TYPE_ (BSET)].sets++
63 #define BITSET_STATS_CACHE_SETS_INC(BSET) \
64 bitset_stats_info->types[BITSET_TYPE_ (BSET)].cache_sets++
65 #define BITSET_STATS_RESETS_INC(BSET) \
66 bitset_stats_info->types[BITSET_TYPE_ (BSET)].resets++
67 #define BITSET_STATS_CACHE_RESETS_INC(BSET) \
68 bitset_stats_info->types[BITSET_TYPE_ (BSET)].cache_resets++
69 #define BITSET_STATS_TESTS_INC(BSET) \
70 bitset_stats_info->types[BITSET_TYPE_ (BSET)].tests++
71 #define BITSET_STATS_CACHE_TESTS_INC(BSET) \
72 bitset_stats_info->types[BITSET_TYPE_ (BSET)].cache_tests++
73 #define BITSET_STATS_LISTS_INC(BSET) \
74 bitset_stats_info->types[BITSET_TYPE_ (BSET)].lists++
75 #define BITSET_STATS_LIST_COUNTS_INC(BSET, I) \
76 bitset_stats_info->types[BITSET_TYPE_ (BSET)].list_counts[(I)]++
77 #define BITSET_STATS_LIST_SIZES_INC(BSET, I) \
78 bitset_stats_info->types[BITSET_TYPE_ (BSET)].list_sizes[(I)]++
79 #define BITSET_STATS_LIST_DENSITY_INC(BSET, I) \
80 bitset_stats_info->types[BITSET_TYPE_ (BSET)].list_density[(I)]++
83 struct bitset_type_info_struct
89 unsigned int cache_sets
;
91 unsigned int cache_resets
;
93 unsigned int cache_tests
;
94 unsigned int list_counts
[BITSET_LOG_COUNT_BINS
];
95 unsigned int list_sizes
[BITSET_LOG_SIZE_BINS
];
96 unsigned int list_density
[BITSET_DENSITY_BINS
];
99 struct bitset_stats_info_struct
102 struct bitset_type_info_struct types
[BITSET_TYPE_NUM
];
106 struct bitset_stats_info_struct bitset_stats_info_data
;
107 struct bitset_stats_info_struct
*bitset_stats_info
;
108 bool bitset_stats_enabled
= false;
111 /* Print a percentage histogram with message MSG to FILE. */
113 bitset_percent_histogram_print (FILE *file
, const char *name
, const char *msg
,
114 unsigned int n_bins
, unsigned int *bins
)
120 for (i
= 0; i
< n_bins
; i
++)
126 fprintf (file
, "%s %s", name
, msg
);
127 for (i
= 0; i
< n_bins
; i
++)
128 fprintf (file
, "%.0f-%.0f%%\t%8u (%5.1f%%)\n",
130 (i
+ 1) * 100.0 / n_bins
, bins
[i
],
131 (100.0 * bins
[i
]) / total
);
135 /* Print a log histogram with message MSG to FILE. */
137 bitset_log_histogram_print (FILE *file
, const char *name
, const char *msg
,
138 unsigned int n_bins
, unsigned int *bins
)
142 unsigned int max_width
;
145 for (i
= 0; i
< n_bins
; i
++)
151 /* Determine number of useful bins. */
152 for (i
= n_bins
; i
> 3 && ! bins
[i
- 1]; i
--)
156 /* 2 * ceil (log10 (2) * (N - 1)) + 1. */
157 max_width
= 2 * (unsigned int) (0.30103 * (n_bins
- 1) + 0.9999) + 1;
159 fprintf (file
, "%s %s", name
, msg
);
160 for (i
= 0; i
< 2; i
++)
161 fprintf (file
, "%*d\t%8u (%5.1f%%)\n",
162 max_width
, i
, bins
[i
], 100.0 * bins
[i
] / total
);
164 for (; i
< n_bins
; i
++)
165 fprintf (file
, "%*lu-%lu\t%8u (%5.1f%%)\n",
166 max_width
- ((unsigned int) (0.30103 * (i
) + 0.9999) + 1),
167 (unsigned long) 1 << (i
- 1),
168 ((unsigned long) 1 << i
) - 1,
170 (100.0 * bins
[i
]) / total
);
174 /* Print bitset statistics to FILE. */
176 bitset_stats_print_1 (FILE *file
, const char *name
,
177 struct bitset_type_info_struct
*stats
)
182 fprintf (file
, "%s:\n", name
);
183 fprintf (file
, _("%u bitset_allocs, %u freed (%.2f%%).\n"),
184 stats
->allocs
, stats
->frees
,
185 stats
->allocs
? 100.0 * stats
->frees
/ stats
->allocs
: 0);
186 fprintf (file
, _("%u bitset_sets, %u cached (%.2f%%)\n"),
187 stats
->sets
, stats
->cache_sets
,
188 stats
->sets
? 100.0 * stats
->cache_sets
/ stats
->sets
: 0);
189 fprintf (file
, _("%u bitset_resets, %u cached (%.2f%%)\n"),
190 stats
->resets
, stats
->cache_resets
,
191 stats
->resets
? 100.0 * stats
->cache_resets
/ stats
->resets
: 0);
192 fprintf (file
, _("%u bitset_tests, %u cached (%.2f%%)\n"),
193 stats
->tests
, stats
->cache_tests
,
194 stats
->tests
? 100.0 * stats
->cache_tests
/ stats
->tests
: 0);
196 fprintf (file
, _("%u bitset_lists\n"), stats
->lists
);
198 bitset_log_histogram_print (file
, name
, _("count log histogram\n"),
199 BITSET_LOG_COUNT_BINS
, stats
->list_counts
);
201 bitset_log_histogram_print (file
, name
, _("size log histogram\n"),
202 BITSET_LOG_SIZE_BINS
, stats
->list_sizes
);
204 bitset_percent_histogram_print (file
, name
, _("density histogram\n"),
205 BITSET_DENSITY_BINS
, stats
->list_density
);
209 /* Print all bitset statistics to FILE. */
211 bitset_stats_print (FILE *file
, bool verbose ATTRIBUTE_UNUSED
)
215 if (!bitset_stats_info
)
218 fprintf (file
, _("Bitset statistics:\n\n"));
220 if (bitset_stats_info
->runs
> 1)
221 fprintf (file
, _("Accumulated runs = %u\n"), bitset_stats_info
->runs
);
223 for (i
= 0; i
< BITSET_TYPE_NUM
; i
++)
224 bitset_stats_print_1 (file
, bitset_type_names
[i
],
225 &bitset_stats_info
->types
[i
]);
229 /* Initialise bitset statistics logging. */
231 bitset_stats_enable (void)
233 if (!bitset_stats_info
)
234 bitset_stats_info
= &bitset_stats_info_data
;
235 bitset_stats_enabled
= true;
240 bitset_stats_disable (void)
242 bitset_stats_enabled
= false;
246 /* Read bitset statistics file. */
248 bitset_stats_read (const char *filename
)
252 if (!bitset_stats_info
)
256 filename
= BITSET_STATS_FILE
;
258 file
= fopen (filename
, "r");
261 if (fread (&bitset_stats_info_data
, sizeof (bitset_stats_info_data
),
265 perror (_("Could not read stats file."));
267 fprintf (stderr
, _("Bad stats file size.\n"));
269 if (fclose (file
) != 0)
270 perror (_("Could not read stats file."));
272 bitset_stats_info_data
.runs
++;
276 /* Write bitset statistics file. */
278 bitset_stats_write (const char *filename
)
282 if (!bitset_stats_info
)
286 filename
= BITSET_STATS_FILE
;
288 file
= fopen (filename
, "w");
291 if (fwrite (&bitset_stats_info_data
, sizeof (bitset_stats_info_data
),
293 perror (_("Could not write stats file."));
294 if (fclose (file
) != 0)
295 perror (_("Could not write stats file."));
298 perror (_("Could not open stats file for writing."));
302 /* Dump bitset statistics to FILE. */
304 bitset_stats_dump (FILE *file
)
306 bitset_stats_print (file
, false);
310 /* Function to be called from debugger to print bitset stats. */
312 debug_bitset_stats (void)
314 bitset_stats_print (stderr
, true);
319 bitset_stats_set (bitset dst
, bitset_bindex bitno
)
321 bitset bset
= dst
->s
.bset
;
322 bitset_windex wordno
= bitno
/ BITSET_WORD_BITS
;
323 bitset_windex offset
= wordno
- bset
->b
.cindex
;
325 BITSET_STATS_SETS_INC (bset
);
327 if (offset
< bset
->b
.csize
)
329 bset
->b
.cdata
[offset
] |= (bitset_word
) 1 << (bitno
% BITSET_WORD_BITS
);
330 BITSET_STATS_CACHE_SETS_INC (bset
);
333 BITSET_SET_ (bset
, bitno
);
338 bitset_stats_reset (bitset dst
, bitset_bindex bitno
)
340 bitset bset
= dst
->s
.bset
;
341 bitset_windex wordno
= bitno
/ BITSET_WORD_BITS
;
342 bitset_windex offset
= wordno
- bset
->b
.cindex
;
344 BITSET_STATS_RESETS_INC (bset
);
346 if (offset
< bset
->b
.csize
)
348 bset
->b
.cdata
[offset
] &=
349 ~((bitset_word
) 1 << (bitno
% BITSET_WORD_BITS
));
350 BITSET_STATS_CACHE_RESETS_INC (bset
);
353 BITSET_RESET_ (bset
, bitno
);
358 bitset_stats_toggle (bitset src
, bitset_bindex bitno
)
360 return BITSET_TOGGLE_ (src
->s
.bset
, bitno
);
365 bitset_stats_test (bitset src
, bitset_bindex bitno
)
367 bitset bset
= src
->s
.bset
;
368 bitset_windex wordno
= bitno
/ BITSET_WORD_BITS
;
369 bitset_windex offset
= wordno
- bset
->b
.cindex
;
371 BITSET_STATS_TESTS_INC (bset
);
373 if (offset
< bset
->b
.csize
)
375 BITSET_STATS_CACHE_TESTS_INC (bset
);
376 return (bset
->b
.cdata
[offset
] >> (bitno
% BITSET_WORD_BITS
)) & 1;
379 return BITSET_TEST_ (bset
, bitno
);
384 bitset_stats_resize (bitset src
, bitset_bindex size
)
386 return BITSET_RESIZE_ (src
->s
.bset
, size
);
391 bitset_stats_size (bitset src
)
393 return BITSET_SIZE_ (src
->s
.bset
);
398 bitset_stats_count (bitset src
)
400 return BITSET_COUNT_ (src
->s
.bset
);
405 bitset_stats_empty_p (bitset dst
)
407 return BITSET_EMPTY_P_ (dst
->s
.bset
);
412 bitset_stats_ones (bitset dst
)
414 BITSET_ONES_ (dst
->s
.bset
);
419 bitset_stats_zero (bitset dst
)
421 BITSET_ZERO_ (dst
->s
.bset
);
426 bitset_stats_copy (bitset dst
, bitset src
)
428 BITSET_CHECK2_ (dst
, src
);
429 BITSET_COPY_ (dst
->s
.bset
, src
->s
.bset
);
434 bitset_stats_disjoint_p (bitset dst
, bitset src
)
436 BITSET_CHECK2_ (dst
, src
);
437 return BITSET_DISJOINT_P_ (dst
->s
.bset
, src
->s
.bset
);
442 bitset_stats_equal_p (bitset dst
, bitset src
)
444 BITSET_CHECK2_ (dst
, src
);
445 return BITSET_EQUAL_P_ (dst
->s
.bset
, src
->s
.bset
);
450 bitset_stats_not (bitset dst
, bitset src
)
452 BITSET_CHECK2_ (dst
, src
);
453 BITSET_NOT_ (dst
->s
.bset
, src
->s
.bset
);
458 bitset_stats_subset_p (bitset dst
, bitset src
)
460 BITSET_CHECK2_ (dst
, src
);
461 return BITSET_SUBSET_P_ (dst
->s
.bset
, src
->s
.bset
);
466 bitset_stats_and (bitset dst
, bitset src1
, bitset src2
)
468 BITSET_CHECK3_ (dst
, src1
, src2
);
469 BITSET_AND_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
);
474 bitset_stats_and_cmp (bitset dst
, bitset src1
, bitset src2
)
476 BITSET_CHECK3_ (dst
, src1
, src2
);
477 return BITSET_AND_CMP_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
);
482 bitset_stats_andn (bitset dst
, bitset src1
, bitset src2
)
484 BITSET_CHECK3_ (dst
, src1
, src2
);
485 BITSET_ANDN_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
);
490 bitset_stats_andn_cmp (bitset dst
, bitset src1
, bitset src2
)
492 BITSET_CHECK3_ (dst
, src1
, src2
);
493 return BITSET_ANDN_CMP_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
);
498 bitset_stats_or (bitset dst
, bitset src1
, bitset src2
)
500 BITSET_CHECK3_ (dst
, src1
, src2
);
501 BITSET_OR_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
);
506 bitset_stats_or_cmp (bitset dst
, bitset src1
, bitset src2
)
508 BITSET_CHECK3_ (dst
, src1
, src2
);
509 return BITSET_OR_CMP_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
);
514 bitset_stats_xor (bitset dst
, bitset src1
, bitset src2
)
516 BITSET_CHECK3_ (dst
, src1
, src2
);
517 BITSET_XOR_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
);
522 bitset_stats_xor_cmp (bitset dst
, bitset src1
, bitset src2
)
524 BITSET_CHECK3_ (dst
, src1
, src2
);
525 return BITSET_XOR_CMP_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
);
530 bitset_stats_and_or (bitset dst
, bitset src1
, bitset src2
, bitset src3
)
532 BITSET_CHECK4_ (dst
, src1
, src2
, src3
);
533 BITSET_AND_OR_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
, src3
->s
.bset
);
538 bitset_stats_and_or_cmp (bitset dst
, bitset src1
, bitset src2
, bitset src3
)
540 BITSET_CHECK4_ (dst
, src1
, src2
, src3
);
541 return BITSET_AND_OR_CMP_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
, src3
->s
.bset
);
546 bitset_stats_andn_or (bitset dst
, bitset src1
, bitset src2
, bitset src3
)
548 BITSET_CHECK4_ (dst
, src1
, src2
, src3
);
549 BITSET_ANDN_OR_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
, src3
->s
.bset
);
554 bitset_stats_andn_or_cmp (bitset dst
, bitset src1
, bitset src2
, bitset src3
)
556 BITSET_CHECK4_ (dst
, src1
, src2
, src3
);
557 return BITSET_ANDN_OR_CMP_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
, src3
->s
.bset
);
562 bitset_stats_or_and (bitset dst
, bitset src1
, bitset src2
, bitset src3
)
564 BITSET_CHECK4_ (dst
, src1
, src2
, src3
);
565 BITSET_OR_AND_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
, src3
->s
.bset
);
570 bitset_stats_or_and_cmp (bitset dst
, bitset src1
, bitset src2
, bitset src3
)
572 BITSET_CHECK4_ (dst
, src1
, src2
, src3
);
573 return BITSET_OR_AND_CMP_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
, src3
->s
.bset
);
578 bitset_stats_list (bitset bset
, bitset_bindex
*list
,
579 bitset_bindex num
, bitset_bindex
*next
)
585 enum bitset_type type
;
587 count
= BITSET_LIST_ (bset
->s
.bset
, list
, num
, next
);
589 type
= BITSET_TYPE_ (bset
->s
.bset
);
590 BITSET_STATS_LISTS_INC (bset
->s
.bset
);
592 /* Log histogram of number of set bits. */
593 for (i
= 0, tmp
= count
; tmp
; tmp
>>= 1, i
++)
595 if (i
>= BITSET_LOG_COUNT_BINS
)
596 i
= BITSET_LOG_COUNT_BINS
- 1;
597 BITSET_STATS_LIST_COUNTS_INC (bset
->s
.bset
, i
);
599 /* Log histogram of number of bits in set. */
600 size
= BITSET_SIZE_ (bset
->s
.bset
);
601 for (i
= 0, tmp
= size
; tmp
; tmp
>>= 1, i
++)
603 if (i
>= BITSET_LOG_SIZE_BINS
)
604 i
= BITSET_LOG_SIZE_BINS
- 1;
605 BITSET_STATS_LIST_SIZES_INC (bset
->s
.bset
, i
);
607 /* Histogram of fraction of bits set. */
608 i
= size
? (count
* BITSET_DENSITY_BINS
) / size
: 0;
609 if (i
>= BITSET_DENSITY_BINS
)
610 i
= BITSET_DENSITY_BINS
- 1;
611 BITSET_STATS_LIST_DENSITY_INC (bset
->s
.bset
, i
);
617 bitset_stats_list_reverse (bitset bset
, bitset_bindex
*list
,
618 bitset_bindex num
, bitset_bindex
*next
)
620 return BITSET_LIST_REVERSE_ (bset
->s
.bset
, list
, num
, next
);
625 bitset_stats_free (bitset bset
)
627 BITSET_STATS_FREES_INC (bset
->s
.bset
);
628 BITSET_FREE_ (bset
->s
.bset
);
632 struct bitset_vtable bitset_stats_vtable
= {
640 bitset_stats_empty_p
,
644 bitset_stats_disjoint_p
,
645 bitset_stats_equal_p
,
647 bitset_stats_subset_p
,
649 bitset_stats_and_cmp
,
651 bitset_stats_andn_cmp
,
655 bitset_stats_xor_cmp
,
657 bitset_stats_and_or_cmp
,
658 bitset_stats_andn_or
,
659 bitset_stats_andn_or_cmp
,
661 bitset_stats_or_and_cmp
,
663 bitset_stats_list_reverse
,
669 /* Return enclosed bitset type. */
671 bitset_stats_type_get (bitset bset
)
673 return BITSET_TYPE_ (bset
->s
.bset
);
678 bitset_stats_bytes (void)
680 return sizeof (struct bitset_stats_struct
);
685 bitset_stats_init (bitset bset
, bitset_bindex n_bits
, enum bitset_type type
)
690 bset
->b
.vtable
= &bitset_stats_vtable
;
697 BITSET_NBITS_ (bset
) = n_bits
;
699 /* Set up the actual bitset implementation that
700 we are a wrapper over. */
704 bytes
= abitset_bytes (n_bits
);
705 sbset
= (bitset
) xcalloc (1, bytes
);
706 abitset_init (sbset
, n_bits
);
710 bytes
= lbitset_bytes (n_bits
);
711 sbset
= (bitset
) xcalloc (1, bytes
);
712 lbitset_init (sbset
, n_bits
);
716 bytes
= ebitset_bytes (n_bits
);
717 sbset
= (bitset
) xcalloc (1, bytes
);
718 ebitset_init (sbset
, n_bits
);
722 bytes
= vbitset_bytes (n_bits
);
723 sbset
= (bitset
) xcalloc (1, bytes
);
724 vbitset_init (sbset
, n_bits
);
731 bset
->s
.bset
= sbset
;
733 BITSET_STATS_ALLOCS_INC (type
);