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 int bitset_stats_size
PARAMS ((bitset
));
124 static int bitset_stats_list
PARAMS ((bitset
, bitset_bindex
*, bitset_bindex
,
126 static int bitset_stats_list_reverse
127 PARAMS ((bitset
, bitset_bindex
*, bitset_bindex
, bitset_bindex
*));
128 static void bitset_stats_free
PARAMS ((bitset
));
129 static void bitset_percent_histogram_print
PARAMS ((FILE *, const char *,
133 static void bitset_log_histogram_print
PARAMS ((FILE *, const char *,
137 static void bitset_stats_print_1
138 PARAMS ((FILE *, const char *, struct bitset_type_info_struct
*));
139 static void bitset_stats_print
PARAMS ((FILE *, int));
142 /* Print a percentage histogram with message MSG to FILE. */
144 bitset_percent_histogram_print (file
, name
, msg
, n_bins
, bins
)
155 for (i
= 0; i
< n_bins
; i
++)
161 fprintf (file
, "%s %s", name
, msg
);
162 for (i
= 0; i
< n_bins
; i
++)
163 fprintf (file
, "%.0f-%.0f%%\t%8d (%5.1f%%)\n",
165 (i
+ 1) * 100.0 / n_bins
, bins
[i
],
166 (100.0 * bins
[i
]) / total
);
170 /* Print a log histogram with message MSG to FILE. */
172 bitset_log_histogram_print (file
, name
, msg
, n_bins
, bins
)
181 unsigned int max_width
;
184 for (i
= 0; i
< n_bins
; i
++)
190 /* Determine number of useful bins. */
191 for (i
= n_bins
; i
> 3 && ! bins
[i
- 1]; i
--)
195 /* 2 * ceil (log10 (2) * (N - 1)) + 1. */
196 max_width
= 2 * (unsigned int) (0.30103 * (n_bins
- 1) + 0.9999) + 1;
198 fprintf (file
, "%s %s", name
, msg
);
199 for (i
= 0; i
< 2; i
++)
200 fprintf (file
, "%*d\t%8d (%5.1f%%)\n",
201 max_width
, i
, bins
[i
], 100.0 * bins
[i
] / total
);
203 for (; i
< n_bins
; i
++)
204 fprintf (file
, "%*d-%d\t%8d (%5.1f%%)\n",
205 max_width
- ((unsigned int) (0.30103 * (i
) + 0.9999) + 1),
206 1 << (i
- 1), (1 << i
) - 1, bins
[i
],
207 (100.0 * bins
[i
]) / total
);
211 /* Print bitset statistics to FILE. */
213 bitset_stats_print_1 (file
, name
, stats
)
216 struct bitset_type_info_struct
*stats
;
221 fprintf (file
, "%s:\n", name
);
222 fprintf (file
, _("%d bitset_allocs, %d freed (%.2f%%).\n"),
223 stats
->allocs
, stats
->frees
,
224 stats
->allocs
? 100.0 * stats
->frees
/ stats
->allocs
: 0);
225 fprintf (file
, _("%d bitset_sets, %d cached (%.2f%%)\n"),
226 stats
->sets
, stats
->cache_sets
,
227 stats
->sets
? 100.0 * stats
->cache_sets
/ stats
->sets
: 0);
228 fprintf (file
, _("%d bitset_resets, %d cached (%.2f%%)\n"),
229 stats
->resets
, stats
->cache_resets
,
230 stats
->resets
? 100.0 * stats
->cache_resets
/ stats
->resets
: 0);
231 fprintf (file
, _("%d bitset_tests, %d cached (%.2f%%)\n"),
232 stats
->tests
, stats
->cache_tests
,
233 stats
->tests
? 100.0 * stats
->cache_tests
/ stats
->tests
: 0);
235 fprintf (file
, _("%d bitset_lists\n"), stats
->lists
);
237 bitset_log_histogram_print (file
, name
, _("count log histogram\n"),
238 BITSET_LOG_COUNT_BINS
, stats
->list_counts
);
240 bitset_log_histogram_print (file
, name
, _("size log histogram\n"),
241 BITSET_LOG_SIZE_BINS
, stats
->list_sizes
);
243 bitset_percent_histogram_print (file
, name
, _("density histogram\n"),
244 BITSET_DENSITY_BINS
, stats
->list_density
);
248 /* Print all bitset statistics to FILE. */
250 bitset_stats_print (file
, verbose
)
252 int verbose ATTRIBUTE_UNUSED
;
256 if (!bitset_stats_info
)
259 fprintf (file
, _("Bitset statistics:\n\n"));
261 if (bitset_stats_info
->runs
> 1)
262 fprintf (file
, _("Accumulated runs = %d\n"), bitset_stats_info
->runs
);
264 for (i
= 0; i
< BITSET_TYPE_NUM
; i
++)
265 bitset_stats_print_1 (file
, bitset_type_names
[i
],
266 &bitset_stats_info
->types
[i
]);
270 /* Initialise bitset statistics logging. */
272 bitset_stats_enable ()
274 if (!bitset_stats_info
)
275 bitset_stats_info
= &bitset_stats_info_data
;
276 bitset_stats_enabled
= 1;
281 bitset_stats_disable ()
283 bitset_stats_enabled
= 0;
287 /* Read bitset statistics file. */
289 bitset_stats_read (filename
)
290 const char *filename
;
294 if (!bitset_stats_info
)
298 filename
= BITSET_STATS_FILE
;
300 file
= fopen (filename
, "r");
303 if (fread (&bitset_stats_info_data
, sizeof (bitset_stats_info_data
),
307 perror (_("Could not read stats file."));
309 fprintf (stderr
, _("Bad stats file size.\n"));
313 bitset_stats_info_data
.runs
++;
317 /* Write bitset statistics file. */
319 bitset_stats_write (filename
)
320 const char *filename
;
324 if (!bitset_stats_info
)
328 filename
= BITSET_STATS_FILE
;
330 file
= fopen (filename
, "w");
333 if (fwrite (&bitset_stats_info_data
, sizeof (bitset_stats_info_data
),
335 perror (_("Could not write stats file."));
339 perror (_("Could not open stats file for writing."));
343 /* Dump bitset statistics to FILE. */
345 bitset_stats_dump (file
)
348 bitset_stats_print (file
, 0);
352 /* Function to be called from debugger to print bitset stats. */
354 debug_bitset_stats (void)
356 bitset_stats_print (stderr
, 1);
361 bitset_stats_set (dst
, bitno
)
365 bitset bset
= dst
->s
.bset
;
366 bitset_windex wordno
= bitno
/ BITSET_WORD_BITS
;
367 bitset_windex offset
= wordno
- bset
->b
.cindex
;
369 BITSET_STATS_SETS_INC (bset
);
371 if (offset
< bset
->b
.csize
)
373 bset
->b
.cdata
[offset
] |= (bitset_word
) 1 << (bitno
% BITSET_WORD_BITS
);
374 BITSET_STATS_CACHE_SETS_INC (bset
);
377 BITSET_SET_ (bset
, bitno
);
382 bitset_stats_reset (dst
, bitno
)
386 bitset bset
= dst
->s
.bset
;
387 bitset_windex wordno
= bitno
/ BITSET_WORD_BITS
;
388 bitset_windex offset
= wordno
- bset
->b
.cindex
;
390 BITSET_STATS_RESETS_INC (bset
);
392 if (offset
< bset
->b
.csize
)
394 bset
->b
.cdata
[offset
] &=
395 ~((bitset_word
) 1 << (bitno
% BITSET_WORD_BITS
));
396 BITSET_STATS_CACHE_RESETS_INC (bset
);
399 BITSET_RESET_ (bset
, bitno
);
404 bitset_stats_toggle (src
, bitno
)
408 return BITSET_TOGGLE_ (src
->s
.bset
, bitno
);
413 bitset_stats_test (src
, bitno
)
417 bitset bset
= src
->s
.bset
;
418 bitset_windex wordno
= bitno
/ BITSET_WORD_BITS
;
419 bitset_windex offset
= wordno
- bset
->b
.cindex
;
421 BITSET_STATS_TESTS_INC (bset
);
423 if (offset
< bset
->b
.csize
)
425 BITSET_STATS_CACHE_TESTS_INC (bset
);
426 return (bset
->b
.cdata
[offset
] >> (bitno
% BITSET_WORD_BITS
)) & 1;
429 return BITSET_TEST_ (bset
, bitno
);
434 bitset_stats_size (src
)
437 return BITSET_SIZE_ (src
->s
.bset
);
442 bitset_stats_count (src
)
445 return BITSET_COUNT_ (src
->s
.bset
);
450 bitset_stats_empty_p (dst
)
453 return BITSET_EMPTY_P_ (dst
->s
.bset
);
458 bitset_stats_ones (dst
)
461 BITSET_ONES_ (dst
->s
.bset
);
466 bitset_stats_zero (dst
)
469 BITSET_ZERO_ (dst
->s
.bset
);
474 bitset_stats_copy (dst
, src
)
478 BITSET_CHECK2_ (dst
, src
);
479 BITSET_COPY_ (dst
->s
.bset
, src
->s
.bset
);
484 bitset_stats_disjoint_p (dst
, src
)
488 BITSET_CHECK2_ (dst
, src
);
489 return BITSET_DISJOINT_P_ (dst
->s
.bset
, src
->s
.bset
);
494 bitset_stats_equal_p (dst
, src
)
498 BITSET_CHECK2_ (dst
, src
);
499 return BITSET_EQUAL_P_ (dst
->s
.bset
, src
->s
.bset
);
504 bitset_stats_not (dst
, src
)
508 BITSET_CHECK2_ (dst
, src
);
509 BITSET_NOT_ (dst
->s
.bset
, src
->s
.bset
);
514 bitset_stats_subset_p (dst
, src
)
518 BITSET_CHECK2_ (dst
, src
);
519 return BITSET_SUBSET_P_ (dst
->s
.bset
, src
->s
.bset
);
524 bitset_stats_and (dst
, src1
, src2
)
529 BITSET_CHECK3_ (dst
, src1
, src2
);
530 BITSET_AND_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
);
535 bitset_stats_and_cmp (dst
, src1
, src2
)
540 BITSET_CHECK3_ (dst
, src1
, src2
);
541 return BITSET_AND_CMP_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
);
546 bitset_stats_andn (dst
, src1
, src2
)
551 BITSET_CHECK3_ (dst
, src1
, src2
);
552 BITSET_ANDN_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
);
557 bitset_stats_andn_cmp (dst
, src1
, src2
)
562 BITSET_CHECK3_ (dst
, src1
, src2
);
563 return BITSET_ANDN_CMP_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
);
568 bitset_stats_or (dst
, src1
, src2
)
573 BITSET_CHECK3_ (dst
, src1
, src2
);
574 BITSET_OR_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
);
579 bitset_stats_or_cmp (dst
, src1
, src2
)
584 BITSET_CHECK3_ (dst
, src1
, src2
);
585 return BITSET_OR_CMP_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
);
590 bitset_stats_xor (dst
, src1
, src2
)
595 BITSET_CHECK3_ (dst
, src1
, src2
);
596 BITSET_XOR_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
);
601 bitset_stats_xor_cmp (dst
, src1
, src2
)
606 BITSET_CHECK3_ (dst
, src1
, src2
);
607 return BITSET_XOR_CMP_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
);
612 bitset_stats_and_or (dst
, src1
, src2
, src3
)
618 BITSET_CHECK4_ (dst
, src1
, src2
, src3
);
620 BITSET_AND_OR_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
, src3
->s
.bset
);
625 bitset_stats_and_or_cmp (dst
, src1
, src2
, src3
)
631 BITSET_CHECK4_ (dst
, src1
, src2
, src3
);
633 return BITSET_AND_OR_CMP_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
, src3
->s
.bset
);
638 bitset_stats_andn_or (dst
, src1
, src2
, src3
)
644 BITSET_CHECK4_ (dst
, src1
, src2
, src3
);
646 BITSET_ANDN_OR_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
, src3
->s
.bset
);
651 bitset_stats_andn_or_cmp (dst
, src1
, src2
, src3
)
657 BITSET_CHECK4_ (dst
, src1
, src2
, src3
);
659 return BITSET_ANDN_OR_CMP_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
, src3
->s
.bset
);
664 bitset_stats_or_and (dst
, src1
, src2
, src3
)
670 BITSET_CHECK4_ (dst
, src1
, src2
, src3
);
672 BITSET_OR_AND_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
, src3
->s
.bset
);
677 bitset_stats_or_and_cmp (dst
, src1
, src2
, src3
)
683 BITSET_CHECK4_ (dst
, src1
, src2
, src3
);
685 return BITSET_OR_AND_CMP_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
, src3
->s
.bset
);
690 bitset_stats_list (bset
, list
, num
, next
)
700 enum bitset_type type
;
702 count
= BITSET_LIST_ (bset
->s
.bset
, list
, num
, next
);
704 type
= BITSET_TYPE_ (bset
->s
.bset
);
705 BITSET_STATS_LISTS_INC (bset
->s
.bset
);
707 /* Log histogram of number of set bits. */
708 for (i
= 0, tmp
= count
; tmp
; tmp
>>= 1, i
++)
710 if (i
>= BITSET_LOG_COUNT_BINS
)
711 i
= BITSET_LOG_COUNT_BINS
- 1;
712 BITSET_STATS_LIST_COUNTS_INC (bset
->s
.bset
, i
);
714 /* Log histogram of number of bits in set. */
715 size
= BITSET_SIZE_ (bset
->s
.bset
);
716 for (i
= 0, tmp
= size
; tmp
; tmp
>>= 1, i
++)
718 if (i
>= BITSET_LOG_SIZE_BINS
)
719 i
= BITSET_LOG_SIZE_BINS
- 1;
720 BITSET_STATS_LIST_SIZES_INC (bset
->s
.bset
, i
);
722 /* Histogram of fraction of bits set. */
723 i
= size
? (count
* BITSET_DENSITY_BINS
) / size
: 0;
724 if (i
>= BITSET_DENSITY_BINS
)
725 i
= BITSET_DENSITY_BINS
- 1;
726 BITSET_STATS_LIST_DENSITY_INC (bset
->s
.bset
, i
);
732 bitset_stats_list_reverse (bset
, list
, num
, next
)
738 return BITSET_LIST_REVERSE_ (bset
->s
.bset
, list
, num
, next
);
743 bitset_stats_free (bset
)
746 BITSET_STATS_FREES_INC (bset
->s
.bset
);
747 BITSET_FREE_ (bset
->s
.bset
);
751 struct bitset_vtable bitset_stats_vtable
= {
758 bitset_stats_empty_p
,
762 bitset_stats_disjoint_p
,
763 bitset_stats_equal_p
,
765 bitset_stats_subset_p
,
767 bitset_stats_and_cmp
,
769 bitset_stats_andn_cmp
,
773 bitset_stats_xor_cmp
,
775 bitset_stats_and_or_cmp
,
776 bitset_stats_andn_or
,
777 bitset_stats_andn_or_cmp
,
779 bitset_stats_or_and_cmp
,
781 bitset_stats_list_reverse
,
787 /* Return enclosed bitset type. */
789 bitset_stats_type_get (bset
)
792 return BITSET_TYPE_ (bset
->s
.bset
);
796 int bitset_stats_bytes (void)
798 return sizeof (struct bitset_struct
);
803 bitset_stats_init (bset
, n_bits
, type
)
805 bitset_bindex n_bits
;
806 enum bitset_type type
;
811 bset
->b
.vtable
= &bitset_stats_vtable
;
818 /* Set up the actual bitset implementation that
819 we are a wrapper over. */
823 bytes
= abitset_bytes (n_bits
);
824 sbset
= (bitset
) xcalloc (1, bytes
);
825 abitset_init (sbset
, n_bits
);
829 bytes
= lbitset_bytes (n_bits
);
830 sbset
= (bitset
) xcalloc (1, bytes
);
831 lbitset_init (sbset
, n_bits
);
835 bytes
= ebitset_bytes (n_bits
);
836 sbset
= (bitset
) xcalloc (1, bytes
);
837 ebitset_init (sbset
, n_bits
);
844 bset
->s
.bset
= sbset
;
846 BITSET_STATS_ALLOCS_INC (type
);