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 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 int bitset_stats_enabled
= 0;
106 static void bitset_stats_set
PARAMS ((bitset
, bitset_bindex
));
107 static void bitset_stats_reset
PARAMS ((bitset
, bitset_bindex
));
108 static int bitset_stats_toggle
PARAMS ((bitset
, bitset_bindex
));
109 static int bitset_stats_test
PARAMS ((bitset
, bitset_bindex
));
110 static bitset_bindex bitset_stats_size
PARAMS ((bitset
));
111 static bitset_bindex bitset_stats_count
PARAMS ((bitset
));
112 static int bitset_stats_empty_p
PARAMS ((bitset
));
113 static void bitset_stats_ones
PARAMS ((bitset
));
114 static void bitset_stats_zero
PARAMS ((bitset
));
115 static void bitset_stats_copy
PARAMS ((bitset
, bitset
));
116 static int bitset_stats_disjoint_p
PARAMS ((bitset
, bitset
));
117 static int bitset_stats_equal_p
PARAMS ((bitset
, bitset
));
118 static void bitset_stats_not
PARAMS ((bitset
, bitset
));
119 static int bitset_stats_subset_p
PARAMS ((bitset
, bitset
));
120 static void bitset_stats_and
PARAMS ((bitset
, bitset
, bitset
));
121 static int bitset_stats_and_cmp
PARAMS ((bitset
, bitset
, bitset
));
122 static void bitset_stats_andn
PARAMS ((bitset
, bitset
, bitset
));
123 static int bitset_stats_andn_cmp
PARAMS ((bitset
, bitset
, bitset
));
124 static void bitset_stats_or
PARAMS ((bitset
, bitset
, bitset
));
125 static int bitset_stats_or_cmp
PARAMS ((bitset
, bitset
, bitset
));
126 static void bitset_stats_xor
PARAMS ((bitset
, bitset
, bitset
));
127 static int bitset_stats_xor_cmp
PARAMS ((bitset
, bitset
, bitset
));
128 static void bitset_stats_and_or
PARAMS ((bitset
, bitset
, bitset
, bitset
));
129 static int bitset_stats_and_or_cmp
PARAMS ((bitset
, bitset
, bitset
, bitset
));
130 static void bitset_stats_andn_or
PARAMS ((bitset
, bitset
, bitset
, bitset
));
131 static int bitset_stats_andn_or_cmp
PARAMS ((bitset
, bitset
, bitset
, bitset
));
132 static void bitset_stats_or_and
PARAMS ((bitset
, bitset
, bitset
, bitset
));
133 static int bitset_stats_or_and_cmp
PARAMS ((bitset
, bitset
, bitset
, bitset
));
134 static bitset_bindex bitset_stats_list
PARAMS ((bitset
, bitset_bindex
*,
137 static bitset_bindex bitset_stats_list_reverse
138 PARAMS ((bitset
, bitset_bindex
*, bitset_bindex
, bitset_bindex
*));
139 static void bitset_stats_free
PARAMS ((bitset
));
140 static void bitset_percent_histogram_print
PARAMS ((FILE *, const char *,
144 static void bitset_log_histogram_print
PARAMS ((FILE *, const char *,
148 static void bitset_stats_print_1
149 PARAMS ((FILE *, const char *, struct bitset_type_info_struct
*));
150 static void bitset_stats_print
PARAMS ((FILE *, int));
153 /* Print a percentage histogram with message MSG to FILE. */
155 bitset_percent_histogram_print (file
, name
, msg
, n_bins
, bins
)
166 for (i
= 0; i
< n_bins
; i
++)
172 fprintf (file
, "%s %s", name
, msg
);
173 for (i
= 0; i
< n_bins
; i
++)
174 fprintf (file
, "%.0f-%.0f%%\t%8u (%5.1f%%)\n",
176 (i
+ 1) * 100.0 / n_bins
, bins
[i
],
177 (100.0 * bins
[i
]) / total
);
181 /* Print a log histogram with message MSG to FILE. */
183 bitset_log_histogram_print (file
, name
, msg
, n_bins
, bins
)
192 unsigned int max_width
;
195 for (i
= 0; i
< n_bins
; i
++)
201 /* Determine number of useful bins. */
202 for (i
= n_bins
; i
> 3 && ! bins
[i
- 1]; i
--)
206 /* 2 * ceil (log10 (2) * (N - 1)) + 1. */
207 max_width
= 2 * (unsigned int) (0.30103 * (n_bins
- 1) + 0.9999) + 1;
209 fprintf (file
, "%s %s", name
, msg
);
210 for (i
= 0; i
< 2; i
++)
211 fprintf (file
, "%*d\t%8u (%5.1f%%)\n",
212 max_width
, i
, bins
[i
], 100.0 * bins
[i
] / total
);
214 for (; i
< n_bins
; i
++)
215 fprintf (file
, "%*lu-%lu\t%8u (%5.1f%%)\n",
216 max_width
- ((unsigned int) (0.30103 * (i
) + 0.9999) + 1),
217 (unsigned long) 1 << (i
- 1),
218 ((unsigned long) 1 << i
) - 1,
220 (100.0 * bins
[i
]) / total
);
224 /* Print bitset statistics to FILE. */
226 bitset_stats_print_1 (file
, name
, stats
)
229 struct bitset_type_info_struct
*stats
;
234 fprintf (file
, "%s:\n", name
);
235 fprintf (file
, _("%u bitset_allocs, %u freed (%.2f%%).\n"),
236 stats
->allocs
, stats
->frees
,
237 stats
->allocs
? 100.0 * stats
->frees
/ stats
->allocs
: 0);
238 fprintf (file
, _("%u bitset_sets, %u cached (%.2f%%)\n"),
239 stats
->sets
, stats
->cache_sets
,
240 stats
->sets
? 100.0 * stats
->cache_sets
/ stats
->sets
: 0);
241 fprintf (file
, _("%u bitset_resets, %u cached (%.2f%%)\n"),
242 stats
->resets
, stats
->cache_resets
,
243 stats
->resets
? 100.0 * stats
->cache_resets
/ stats
->resets
: 0);
244 fprintf (file
, _("%u bitset_tests, %u cached (%.2f%%)\n"),
245 stats
->tests
, stats
->cache_tests
,
246 stats
->tests
? 100.0 * stats
->cache_tests
/ stats
->tests
: 0);
248 fprintf (file
, _("%u bitset_lists\n"), stats
->lists
);
250 bitset_log_histogram_print (file
, name
, _("count log histogram\n"),
251 BITSET_LOG_COUNT_BINS
, stats
->list_counts
);
253 bitset_log_histogram_print (file
, name
, _("size log histogram\n"),
254 BITSET_LOG_SIZE_BINS
, stats
->list_sizes
);
256 bitset_percent_histogram_print (file
, name
, _("density histogram\n"),
257 BITSET_DENSITY_BINS
, stats
->list_density
);
261 /* Print all bitset statistics to FILE. */
263 bitset_stats_print (file
, verbose
)
265 int verbose ATTRIBUTE_UNUSED
;
269 if (!bitset_stats_info
)
272 fprintf (file
, _("Bitset statistics:\n\n"));
274 if (bitset_stats_info
->runs
> 1)
275 fprintf (file
, _("Accumulated runs = %u\n"), bitset_stats_info
->runs
);
277 for (i
= 0; i
< BITSET_TYPE_NUM
; i
++)
278 bitset_stats_print_1 (file
, bitset_type_names
[i
],
279 &bitset_stats_info
->types
[i
]);
283 /* Initialise bitset statistics logging. */
285 bitset_stats_enable ()
287 if (!bitset_stats_info
)
288 bitset_stats_info
= &bitset_stats_info_data
;
289 bitset_stats_enabled
= 1;
294 bitset_stats_disable ()
296 bitset_stats_enabled
= 0;
300 /* Read bitset statistics file. */
302 bitset_stats_read (filename
)
303 const char *filename
;
307 if (!bitset_stats_info
)
311 filename
= BITSET_STATS_FILE
;
313 file
= fopen (filename
, "r");
316 if (fread (&bitset_stats_info_data
, sizeof (bitset_stats_info_data
),
320 perror (_("Could not read stats file."));
322 fprintf (stderr
, _("Bad stats file size.\n"));
326 bitset_stats_info_data
.runs
++;
330 /* Write bitset statistics file. */
332 bitset_stats_write (filename
)
333 const char *filename
;
337 if (!bitset_stats_info
)
341 filename
= BITSET_STATS_FILE
;
343 file
= fopen (filename
, "w");
346 if (fwrite (&bitset_stats_info_data
, sizeof (bitset_stats_info_data
),
348 perror (_("Could not write stats file."));
352 perror (_("Could not open stats file for writing."));
356 /* Dump bitset statistics to FILE. */
358 bitset_stats_dump (file
)
361 bitset_stats_print (file
, 0);
365 /* Function to be called from debugger to print bitset stats. */
367 debug_bitset_stats (void)
369 bitset_stats_print (stderr
, 1);
374 bitset_stats_set (dst
, bitno
)
378 bitset bset
= dst
->s
.bset
;
379 bitset_windex wordno
= bitno
/ BITSET_WORD_BITS
;
380 bitset_windex offset
= wordno
- bset
->b
.cindex
;
382 BITSET_STATS_SETS_INC (bset
);
384 if (offset
< bset
->b
.csize
)
386 bset
->b
.cdata
[offset
] |= (bitset_word
) 1 << (bitno
% BITSET_WORD_BITS
);
387 BITSET_STATS_CACHE_SETS_INC (bset
);
390 BITSET_SET_ (bset
, bitno
);
395 bitset_stats_reset (dst
, bitno
)
399 bitset bset
= dst
->s
.bset
;
400 bitset_windex wordno
= bitno
/ BITSET_WORD_BITS
;
401 bitset_windex offset
= wordno
- bset
->b
.cindex
;
403 BITSET_STATS_RESETS_INC (bset
);
405 if (offset
< bset
->b
.csize
)
407 bset
->b
.cdata
[offset
] &=
408 ~((bitset_word
) 1 << (bitno
% BITSET_WORD_BITS
));
409 BITSET_STATS_CACHE_RESETS_INC (bset
);
412 BITSET_RESET_ (bset
, bitno
);
417 bitset_stats_toggle (src
, bitno
)
421 return BITSET_TOGGLE_ (src
->s
.bset
, bitno
);
426 bitset_stats_test (src
, bitno
)
430 bitset bset
= src
->s
.bset
;
431 bitset_windex wordno
= bitno
/ BITSET_WORD_BITS
;
432 bitset_windex offset
= wordno
- bset
->b
.cindex
;
434 BITSET_STATS_TESTS_INC (bset
);
436 if (offset
< bset
->b
.csize
)
438 BITSET_STATS_CACHE_TESTS_INC (bset
);
439 return (bset
->b
.cdata
[offset
] >> (bitno
% BITSET_WORD_BITS
)) & 1;
442 return BITSET_TEST_ (bset
, bitno
);
447 bitset_stats_size (src
)
450 return BITSET_SIZE_ (src
->s
.bset
);
455 bitset_stats_count (src
)
458 return BITSET_COUNT_ (src
->s
.bset
);
463 bitset_stats_empty_p (dst
)
466 return BITSET_EMPTY_P_ (dst
->s
.bset
);
471 bitset_stats_ones (dst
)
474 BITSET_ONES_ (dst
->s
.bset
);
479 bitset_stats_zero (dst
)
482 BITSET_ZERO_ (dst
->s
.bset
);
487 bitset_stats_copy (dst
, src
)
491 BITSET_CHECK2_ (dst
, src
);
492 BITSET_COPY_ (dst
->s
.bset
, src
->s
.bset
);
497 bitset_stats_disjoint_p (dst
, src
)
501 BITSET_CHECK2_ (dst
, src
);
502 return BITSET_DISJOINT_P_ (dst
->s
.bset
, src
->s
.bset
);
507 bitset_stats_equal_p (dst
, src
)
511 BITSET_CHECK2_ (dst
, src
);
512 return BITSET_EQUAL_P_ (dst
->s
.bset
, src
->s
.bset
);
517 bitset_stats_not (dst
, src
)
521 BITSET_CHECK2_ (dst
, src
);
522 BITSET_NOT_ (dst
->s
.bset
, src
->s
.bset
);
527 bitset_stats_subset_p (dst
, src
)
531 BITSET_CHECK2_ (dst
, src
);
532 return BITSET_SUBSET_P_ (dst
->s
.bset
, src
->s
.bset
);
537 bitset_stats_and (dst
, src1
, src2
)
542 BITSET_CHECK3_ (dst
, src1
, src2
);
543 BITSET_AND_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
);
548 bitset_stats_and_cmp (dst
, src1
, src2
)
553 BITSET_CHECK3_ (dst
, src1
, src2
);
554 return BITSET_AND_CMP_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
);
559 bitset_stats_andn (dst
, src1
, src2
)
564 BITSET_CHECK3_ (dst
, src1
, src2
);
565 BITSET_ANDN_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
);
570 bitset_stats_andn_cmp (dst
, src1
, src2
)
575 BITSET_CHECK3_ (dst
, src1
, src2
);
576 return BITSET_ANDN_CMP_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
);
581 bitset_stats_or (dst
, src1
, src2
)
586 BITSET_CHECK3_ (dst
, src1
, src2
);
587 BITSET_OR_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
);
592 bitset_stats_or_cmp (dst
, src1
, src2
)
597 BITSET_CHECK3_ (dst
, src1
, src2
);
598 return BITSET_OR_CMP_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
);
603 bitset_stats_xor (dst
, src1
, src2
)
608 BITSET_CHECK3_ (dst
, src1
, src2
);
609 BITSET_XOR_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
);
614 bitset_stats_xor_cmp (dst
, src1
, src2
)
619 BITSET_CHECK3_ (dst
, src1
, src2
);
620 return BITSET_XOR_CMP_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
);
625 bitset_stats_and_or (dst
, src1
, src2
, src3
)
631 BITSET_CHECK4_ (dst
, src1
, src2
, src3
);
633 BITSET_AND_OR_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
, src3
->s
.bset
);
638 bitset_stats_and_or_cmp (dst
, src1
, src2
, src3
)
644 BITSET_CHECK4_ (dst
, src1
, src2
, src3
);
646 return BITSET_AND_OR_CMP_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
, src3
->s
.bset
);
651 bitset_stats_andn_or (dst
, src1
, src2
, src3
)
657 BITSET_CHECK4_ (dst
, src1
, src2
, src3
);
659 BITSET_ANDN_OR_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
, src3
->s
.bset
);
664 bitset_stats_andn_or_cmp (dst
, src1
, src2
, src3
)
670 BITSET_CHECK4_ (dst
, src1
, src2
, src3
);
672 return BITSET_ANDN_OR_CMP_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
, src3
->s
.bset
);
677 bitset_stats_or_and (dst
, src1
, src2
, src3
)
683 BITSET_CHECK4_ (dst
, src1
, src2
, src3
);
685 BITSET_OR_AND_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
, src3
->s
.bset
);
690 bitset_stats_or_and_cmp (dst
, src1
, src2
, src3
)
696 BITSET_CHECK4_ (dst
, src1
, src2
, src3
);
698 return BITSET_OR_AND_CMP_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
, src3
->s
.bset
);
703 bitset_stats_list (bset
, list
, num
, next
)
713 enum bitset_type type
;
715 count
= BITSET_LIST_ (bset
->s
.bset
, list
, num
, next
);
717 type
= BITSET_TYPE_ (bset
->s
.bset
);
718 BITSET_STATS_LISTS_INC (bset
->s
.bset
);
720 /* Log histogram of number of set bits. */
721 for (i
= 0, tmp
= count
; tmp
; tmp
>>= 1, i
++)
723 if (i
>= BITSET_LOG_COUNT_BINS
)
724 i
= BITSET_LOG_COUNT_BINS
- 1;
725 BITSET_STATS_LIST_COUNTS_INC (bset
->s
.bset
, i
);
727 /* Log histogram of number of bits in set. */
728 size
= BITSET_SIZE_ (bset
->s
.bset
);
729 for (i
= 0, tmp
= size
; tmp
; tmp
>>= 1, i
++)
731 if (i
>= BITSET_LOG_SIZE_BINS
)
732 i
= BITSET_LOG_SIZE_BINS
- 1;
733 BITSET_STATS_LIST_SIZES_INC (bset
->s
.bset
, i
);
735 /* Histogram of fraction of bits set. */
736 i
= size
? (count
* BITSET_DENSITY_BINS
) / size
: 0;
737 if (i
>= BITSET_DENSITY_BINS
)
738 i
= BITSET_DENSITY_BINS
- 1;
739 BITSET_STATS_LIST_DENSITY_INC (bset
->s
.bset
, i
);
745 bitset_stats_list_reverse (bset
, list
, num
, next
)
751 return BITSET_LIST_REVERSE_ (bset
->s
.bset
, list
, num
, next
);
756 bitset_stats_free (bset
)
759 BITSET_STATS_FREES_INC (bset
->s
.bset
);
760 BITSET_FREE_ (bset
->s
.bset
);
764 struct bitset_vtable bitset_stats_vtable
= {
771 bitset_stats_empty_p
,
775 bitset_stats_disjoint_p
,
776 bitset_stats_equal_p
,
778 bitset_stats_subset_p
,
780 bitset_stats_and_cmp
,
782 bitset_stats_andn_cmp
,
786 bitset_stats_xor_cmp
,
788 bitset_stats_and_or_cmp
,
789 bitset_stats_andn_or
,
790 bitset_stats_andn_or_cmp
,
792 bitset_stats_or_and_cmp
,
794 bitset_stats_list_reverse
,
800 /* Return enclosed bitset type. */
802 bitset_stats_type_get (bset
)
805 return BITSET_TYPE_ (bset
->s
.bset
);
810 bitset_stats_bytes (void)
812 return sizeof (struct bitset_stats_struct
);
817 bitset_stats_init (bset
, n_bits
, type
)
819 bitset_bindex n_bits
;
820 enum_bitset_type type
;
825 bset
->b
.vtable
= &bitset_stats_vtable
;
832 /* Set up the actual bitset implementation that
833 we are a wrapper over. */
837 bytes
= abitset_bytes (n_bits
);
838 sbset
= (bitset
) xcalloc (1, bytes
);
839 abitset_init (sbset
, n_bits
);
843 bytes
= lbitset_bytes (n_bits
);
844 sbset
= (bitset
) xcalloc (1, bytes
);
845 lbitset_init (sbset
, n_bits
);
849 bytes
= ebitset_bytes (n_bits
);
850 sbset
= (bitset
) xcalloc (1, bytes
);
851 ebitset_init (sbset
, n_bits
);
858 bset
->s
.bset
= sbset
;
860 BITSET_STATS_ALLOCS_INC (type
);