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
36 #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 typedef struct bitset_stats_struct
86 struct bbitset_struct b
;
87 struct bitset_stats_struct s
;
91 struct bitset_type_info_struct
97 unsigned int cache_sets
;
99 unsigned int cache_resets
;
101 unsigned int cache_tests
;
102 unsigned int list_counts
[BITSET_LOG_COUNT_BINS
];
103 unsigned int list_sizes
[BITSET_LOG_SIZE_BINS
];
104 unsigned int list_density
[BITSET_DENSITY_BINS
];
107 struct bitset_stats_info_struct
110 struct bitset_type_info_struct types
[BITSET_TYPE_NUM
];
114 struct bitset_stats_info_struct bitset_stats_info_data
;
115 struct bitset_stats_info_struct
*bitset_stats_info
;
116 int bitset_stats_enabled
= 0;
119 static void bitset_stats_set
PARAMS ((bitset
, bitset_bindex
));
120 static void bitset_stats_reset
PARAMS ((bitset
, bitset_bindex
));
121 static int bitset_stats_toggle
PARAMS ((bitset
, bitset_bindex
));
122 static int bitset_stats_test
PARAMS ((bitset
, bitset_bindex
));
123 static bitset_bindex bitset_stats_size
PARAMS ((bitset
));
124 static bitset_bindex bitset_stats_list
PARAMS ((bitset
, bitset_bindex
*,
127 static bitset_bindex bitset_stats_list_reverse
128 PARAMS ((bitset
, bitset_bindex
*, bitset_bindex
, bitset_bindex
*));
129 static void bitset_stats_free
PARAMS ((bitset
));
130 static void bitset_percent_histogram_print
PARAMS ((FILE *, const char *,
134 static void bitset_log_histogram_print
PARAMS ((FILE *, const char *,
138 static void bitset_stats_print_1
139 PARAMS ((FILE *, const char *, struct bitset_type_info_struct
*));
140 static void bitset_stats_print
PARAMS ((FILE *, int));
143 /* Print a percentage histogram with message MSG to FILE. */
145 bitset_percent_histogram_print (file
, name
, msg
, n_bins
, bins
)
156 for (i
= 0; i
< n_bins
; i
++)
162 fprintf (file
, "%s %s", name
, msg
);
163 for (i
= 0; i
< n_bins
; i
++)
164 fprintf (file
, "%.0f-%.0f%%\t%8u (%5.1f%%)\n",
166 (i
+ 1) * 100.0 / n_bins
, bins
[i
],
167 (100.0 * bins
[i
]) / total
);
171 /* Print a log histogram with message MSG to FILE. */
173 bitset_log_histogram_print (file
, name
, msg
, n_bins
, bins
)
182 unsigned int max_width
;
185 for (i
= 0; i
< n_bins
; i
++)
191 /* Determine number of useful bins. */
192 for (i
= n_bins
; i
> 3 && ! bins
[i
- 1]; i
--)
196 /* 2 * ceil (log10 (2) * (N - 1)) + 1. */
197 max_width
= 2 * (unsigned int) (0.30103 * (n_bins
- 1) + 0.9999) + 1;
199 fprintf (file
, "%s %s", name
, msg
);
200 for (i
= 0; i
< 2; i
++)
201 fprintf (file
, "%*d\t%8u (%5.1f%%)\n",
202 max_width
, i
, bins
[i
], 100.0 * bins
[i
] / total
);
204 for (; i
< n_bins
; i
++)
205 fprintf (file
, "%*lu-%lu\t%8u (%5.1f%%)\n",
206 max_width
- ((unsigned int) (0.30103 * (i
) + 0.9999) + 1),
207 (unsigned long) 1 << (i
- 1),
208 ((unsigned long) 1 << i
) - 1,
210 (100.0 * bins
[i
]) / total
);
214 /* Print bitset statistics to FILE. */
216 bitset_stats_print_1 (file
, name
, stats
)
219 struct bitset_type_info_struct
*stats
;
224 fprintf (file
, "%s:\n", name
);
225 fprintf (file
, _("%u bitset_allocs, %u freed (%.2f%%).\n"),
226 stats
->allocs
, stats
->frees
,
227 stats
->allocs
? 100.0 * stats
->frees
/ stats
->allocs
: 0);
228 fprintf (file
, _("%u bitset_sets, %u cached (%.2f%%)\n"),
229 stats
->sets
, stats
->cache_sets
,
230 stats
->sets
? 100.0 * stats
->cache_sets
/ stats
->sets
: 0);
231 fprintf (file
, _("%u bitset_resets, %u cached (%.2f%%)\n"),
232 stats
->resets
, stats
->cache_resets
,
233 stats
->resets
? 100.0 * stats
->cache_resets
/ stats
->resets
: 0);
234 fprintf (file
, _("%u bitset_tests, %u cached (%.2f%%)\n"),
235 stats
->tests
, stats
->cache_tests
,
236 stats
->tests
? 100.0 * stats
->cache_tests
/ stats
->tests
: 0);
238 fprintf (file
, _("%u bitset_lists\n"), stats
->lists
);
240 bitset_log_histogram_print (file
, name
, _("count log histogram\n"),
241 BITSET_LOG_COUNT_BINS
, stats
->list_counts
);
243 bitset_log_histogram_print (file
, name
, _("size log histogram\n"),
244 BITSET_LOG_SIZE_BINS
, stats
->list_sizes
);
246 bitset_percent_histogram_print (file
, name
, _("density histogram\n"),
247 BITSET_DENSITY_BINS
, stats
->list_density
);
251 /* Print all bitset statistics to FILE. */
253 bitset_stats_print (file
, verbose
)
255 int verbose ATTRIBUTE_UNUSED
;
259 if (!bitset_stats_info
)
262 fprintf (file
, _("Bitset statistics:\n\n"));
264 if (bitset_stats_info
->runs
> 1)
265 fprintf (file
, _("Accumulated runs = %u\n"), bitset_stats_info
->runs
);
267 for (i
= 0; i
< BITSET_TYPE_NUM
; i
++)
268 bitset_stats_print_1 (file
, bitset_type_names
[i
],
269 &bitset_stats_info
->types
[i
]);
273 /* Initialise bitset statistics logging. */
275 bitset_stats_enable ()
277 if (!bitset_stats_info
)
278 bitset_stats_info
= &bitset_stats_info_data
;
279 bitset_stats_enabled
= 1;
284 bitset_stats_disable ()
286 bitset_stats_enabled
= 0;
290 /* Read bitset statistics file. */
292 bitset_stats_read (filename
)
293 const char *filename
;
297 if (!bitset_stats_info
)
301 filename
= BITSET_STATS_FILE
;
303 file
= fopen (filename
, "r");
306 if (fread (&bitset_stats_info_data
, sizeof (bitset_stats_info_data
),
310 perror (_("Could not read stats file."));
312 fprintf (stderr
, _("Bad stats file size.\n"));
316 bitset_stats_info_data
.runs
++;
320 /* Write bitset statistics file. */
322 bitset_stats_write (filename
)
323 const char *filename
;
327 if (!bitset_stats_info
)
331 filename
= BITSET_STATS_FILE
;
333 file
= fopen (filename
, "w");
336 if (fwrite (&bitset_stats_info_data
, sizeof (bitset_stats_info_data
),
338 perror (_("Could not write stats file."));
342 perror (_("Could not open stats file for writing."));
346 /* Dump bitset statistics to FILE. */
348 bitset_stats_dump (file
)
351 bitset_stats_print (file
, 0);
355 /* Function to be called from debugger to print bitset stats. */
357 debug_bitset_stats (void)
359 bitset_stats_print (stderr
, 1);
364 bitset_stats_set (dst
, bitno
)
368 bitset bset
= dst
->s
.bset
;
369 bitset_windex wordno
= bitno
/ BITSET_WORD_BITS
;
370 bitset_windex offset
= wordno
- bset
->b
.cindex
;
372 BITSET_STATS_SETS_INC (bset
);
374 if (offset
< bset
->b
.csize
)
376 bset
->b
.cdata
[offset
] |= (bitset_word
) 1 << (bitno
% BITSET_WORD_BITS
);
377 BITSET_STATS_CACHE_SETS_INC (bset
);
380 BITSET_SET_ (bset
, bitno
);
385 bitset_stats_reset (dst
, bitno
)
389 bitset bset
= dst
->s
.bset
;
390 bitset_windex wordno
= bitno
/ BITSET_WORD_BITS
;
391 bitset_windex offset
= wordno
- bset
->b
.cindex
;
393 BITSET_STATS_RESETS_INC (bset
);
395 if (offset
< bset
->b
.csize
)
397 bset
->b
.cdata
[offset
] &=
398 ~((bitset_word
) 1 << (bitno
% BITSET_WORD_BITS
));
399 BITSET_STATS_CACHE_RESETS_INC (bset
);
402 BITSET_RESET_ (bset
, bitno
);
407 bitset_stats_toggle (src
, bitno
)
411 return BITSET_TOGGLE_ (src
->s
.bset
, bitno
);
416 bitset_stats_test (src
, bitno
)
420 bitset bset
= src
->s
.bset
;
421 bitset_windex wordno
= bitno
/ BITSET_WORD_BITS
;
422 bitset_windex offset
= wordno
- bset
->b
.cindex
;
424 BITSET_STATS_TESTS_INC (bset
);
426 if (offset
< bset
->b
.csize
)
428 BITSET_STATS_CACHE_TESTS_INC (bset
);
429 return (bset
->b
.cdata
[offset
] >> (bitno
% BITSET_WORD_BITS
)) & 1;
432 return BITSET_TEST_ (bset
, bitno
);
437 bitset_stats_size (src
)
440 return BITSET_SIZE_ (src
->s
.bset
);
445 bitset_stats_count (src
)
448 return BITSET_COUNT_ (src
->s
.bset
);
453 bitset_stats_empty_p (dst
)
456 return BITSET_EMPTY_P_ (dst
->s
.bset
);
461 bitset_stats_ones (dst
)
464 BITSET_ONES_ (dst
->s
.bset
);
469 bitset_stats_zero (dst
)
472 BITSET_ZERO_ (dst
->s
.bset
);
477 bitset_stats_copy (dst
, src
)
481 BITSET_CHECK2_ (dst
, src
);
482 BITSET_COPY_ (dst
->s
.bset
, src
->s
.bset
);
487 bitset_stats_disjoint_p (dst
, src
)
491 BITSET_CHECK2_ (dst
, src
);
492 return BITSET_DISJOINT_P_ (dst
->s
.bset
, src
->s
.bset
);
497 bitset_stats_equal_p (dst
, src
)
501 BITSET_CHECK2_ (dst
, src
);
502 return BITSET_EQUAL_P_ (dst
->s
.bset
, src
->s
.bset
);
507 bitset_stats_not (dst
, src
)
511 BITSET_CHECK2_ (dst
, src
);
512 BITSET_NOT_ (dst
->s
.bset
, src
->s
.bset
);
517 bitset_stats_subset_p (dst
, src
)
521 BITSET_CHECK2_ (dst
, src
);
522 return BITSET_SUBSET_P_ (dst
->s
.bset
, src
->s
.bset
);
527 bitset_stats_and (dst
, src1
, src2
)
532 BITSET_CHECK3_ (dst
, src1
, src2
);
533 BITSET_AND_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
);
538 bitset_stats_and_cmp (dst
, src1
, src2
)
543 BITSET_CHECK3_ (dst
, src1
, src2
);
544 return BITSET_AND_CMP_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
);
549 bitset_stats_andn (dst
, src1
, src2
)
554 BITSET_CHECK3_ (dst
, src1
, src2
);
555 BITSET_ANDN_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
);
560 bitset_stats_andn_cmp (dst
, src1
, src2
)
565 BITSET_CHECK3_ (dst
, src1
, src2
);
566 return BITSET_ANDN_CMP_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
);
571 bitset_stats_or (dst
, src1
, src2
)
576 BITSET_CHECK3_ (dst
, src1
, src2
);
577 BITSET_OR_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
);
582 bitset_stats_or_cmp (dst
, src1
, src2
)
587 BITSET_CHECK3_ (dst
, src1
, src2
);
588 return BITSET_OR_CMP_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
);
593 bitset_stats_xor (dst
, src1
, src2
)
598 BITSET_CHECK3_ (dst
, src1
, src2
);
599 BITSET_XOR_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
);
604 bitset_stats_xor_cmp (dst
, src1
, src2
)
609 BITSET_CHECK3_ (dst
, src1
, src2
);
610 return BITSET_XOR_CMP_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
);
615 bitset_stats_and_or (dst
, src1
, src2
, src3
)
621 BITSET_CHECK4_ (dst
, src1
, src2
, src3
);
623 BITSET_AND_OR_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
, src3
->s
.bset
);
628 bitset_stats_and_or_cmp (dst
, src1
, src2
, src3
)
634 BITSET_CHECK4_ (dst
, src1
, src2
, src3
);
636 return BITSET_AND_OR_CMP_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
, src3
->s
.bset
);
641 bitset_stats_andn_or (dst
, src1
, src2
, src3
)
647 BITSET_CHECK4_ (dst
, src1
, src2
, src3
);
649 BITSET_ANDN_OR_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
, src3
->s
.bset
);
654 bitset_stats_andn_or_cmp (dst
, src1
, src2
, src3
)
660 BITSET_CHECK4_ (dst
, src1
, src2
, src3
);
662 return BITSET_ANDN_OR_CMP_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
, src3
->s
.bset
);
667 bitset_stats_or_and (dst
, src1
, src2
, src3
)
673 BITSET_CHECK4_ (dst
, src1
, src2
, src3
);
675 BITSET_OR_AND_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
, src3
->s
.bset
);
680 bitset_stats_or_and_cmp (dst
, src1
, src2
, src3
)
686 BITSET_CHECK4_ (dst
, src1
, src2
, src3
);
688 return BITSET_OR_AND_CMP_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
, src3
->s
.bset
);
693 bitset_stats_list (bset
, list
, num
, next
)
703 enum bitset_type type
;
705 count
= BITSET_LIST_ (bset
->s
.bset
, list
, num
, next
);
707 type
= BITSET_TYPE_ (bset
->s
.bset
);
708 BITSET_STATS_LISTS_INC (bset
->s
.bset
);
710 /* Log histogram of number of set bits. */
711 for (i
= 0, tmp
= count
; tmp
; tmp
>>= 1, i
++)
713 if (i
>= BITSET_LOG_COUNT_BINS
)
714 i
= BITSET_LOG_COUNT_BINS
- 1;
715 BITSET_STATS_LIST_COUNTS_INC (bset
->s
.bset
, i
);
717 /* Log histogram of number of bits in set. */
718 size
= BITSET_SIZE_ (bset
->s
.bset
);
719 for (i
= 0, tmp
= size
; tmp
; tmp
>>= 1, i
++)
721 if (i
>= BITSET_LOG_SIZE_BINS
)
722 i
= BITSET_LOG_SIZE_BINS
- 1;
723 BITSET_STATS_LIST_SIZES_INC (bset
->s
.bset
, i
);
725 /* Histogram of fraction of bits set. */
726 i
= size
? (count
* BITSET_DENSITY_BINS
) / size
: 0;
727 if (i
>= BITSET_DENSITY_BINS
)
728 i
= BITSET_DENSITY_BINS
- 1;
729 BITSET_STATS_LIST_DENSITY_INC (bset
->s
.bset
, i
);
735 bitset_stats_list_reverse (bset
, list
, num
, next
)
741 return BITSET_LIST_REVERSE_ (bset
->s
.bset
, list
, num
, next
);
746 bitset_stats_free (bset
)
749 BITSET_STATS_FREES_INC (bset
->s
.bset
);
750 BITSET_FREE_ (bset
->s
.bset
);
754 struct bitset_vtable bitset_stats_vtable
= {
761 bitset_stats_empty_p
,
765 bitset_stats_disjoint_p
,
766 bitset_stats_equal_p
,
768 bitset_stats_subset_p
,
770 bitset_stats_and_cmp
,
772 bitset_stats_andn_cmp
,
776 bitset_stats_xor_cmp
,
778 bitset_stats_and_or_cmp
,
779 bitset_stats_andn_or
,
780 bitset_stats_andn_or_cmp
,
782 bitset_stats_or_and_cmp
,
784 bitset_stats_list_reverse
,
790 /* Return enclosed bitset type. */
792 bitset_stats_type_get (bset
)
795 return BITSET_TYPE_ (bset
->s
.bset
);
800 bitset_stats_bytes (void)
802 return sizeof (struct bitset_struct
);
807 bitset_stats_init (bset
, n_bits
, type
)
809 bitset_bindex n_bits
;
810 enum bitset_type type
;
815 bset
->b
.vtable
= &bitset_stats_vtable
;
822 /* Set up the actual bitset implementation that
823 we are a wrapper over. */
827 bytes
= abitset_bytes (n_bits
);
828 sbset
= (bitset
) xcalloc (1, bytes
);
829 abitset_init (sbset
, n_bits
);
833 bytes
= lbitset_bytes (n_bits
);
834 sbset
= (bitset
) xcalloc (1, bytes
);
835 lbitset_init (sbset
, n_bits
);
839 bytes
= ebitset_bytes (n_bits
);
840 sbset
= (bitset
) xcalloc (1, bytes
);
841 ebitset_init (sbset
, n_bits
);
848 bset
->s
.bset
= sbset
;
850 BITSET_STATS_ALLOCS_INC (type
);