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 /* Print a percentage histogram with message MSG to FILE. */
108 bitset_percent_histogram_print (FILE *file
, const char *name
, const char *msg
,
109 unsigned int n_bins
, unsigned int *bins
)
115 for (i
= 0; i
< n_bins
; i
++)
121 fprintf (file
, "%s %s", name
, msg
);
122 for (i
= 0; i
< n_bins
; i
++)
123 fprintf (file
, "%.0f-%.0f%%\t%8u (%5.1f%%)\n",
125 (i
+ 1) * 100.0 / n_bins
, bins
[i
],
126 (100.0 * bins
[i
]) / total
);
130 /* Print a log histogram with message MSG to FILE. */
132 bitset_log_histogram_print (FILE *file
, const char *name
, const char *msg
,
133 unsigned int n_bins
, unsigned int *bins
)
137 unsigned int max_width
;
140 for (i
= 0; i
< n_bins
; i
++)
146 /* Determine number of useful bins. */
147 for (i
= n_bins
; i
> 3 && ! bins
[i
- 1]; i
--)
151 /* 2 * ceil (log10 (2) * (N - 1)) + 1. */
152 max_width
= 2 * (unsigned int) (0.30103 * (n_bins
- 1) + 0.9999) + 1;
154 fprintf (file
, "%s %s", name
, msg
);
155 for (i
= 0; i
< 2; i
++)
156 fprintf (file
, "%*d\t%8u (%5.1f%%)\n",
157 max_width
, i
, bins
[i
], 100.0 * bins
[i
] / total
);
159 for (; i
< n_bins
; i
++)
160 fprintf (file
, "%*lu-%lu\t%8u (%5.1f%%)\n",
161 max_width
- ((unsigned int) (0.30103 * (i
) + 0.9999) + 1),
162 (unsigned long) 1 << (i
- 1),
163 ((unsigned long) 1 << i
) - 1,
165 (100.0 * bins
[i
]) / total
);
169 /* Print bitset statistics to FILE. */
171 bitset_stats_print_1 (FILE *file
, const char *name
,
172 struct bitset_type_info_struct
*stats
)
177 fprintf (file
, "%s:\n", name
);
178 fprintf (file
, _("%u bitset_allocs, %u freed (%.2f%%).\n"),
179 stats
->allocs
, stats
->frees
,
180 stats
->allocs
? 100.0 * stats
->frees
/ stats
->allocs
: 0);
181 fprintf (file
, _("%u bitset_sets, %u cached (%.2f%%)\n"),
182 stats
->sets
, stats
->cache_sets
,
183 stats
->sets
? 100.0 * stats
->cache_sets
/ stats
->sets
: 0);
184 fprintf (file
, _("%u bitset_resets, %u cached (%.2f%%)\n"),
185 stats
->resets
, stats
->cache_resets
,
186 stats
->resets
? 100.0 * stats
->cache_resets
/ stats
->resets
: 0);
187 fprintf (file
, _("%u bitset_tests, %u cached (%.2f%%)\n"),
188 stats
->tests
, stats
->cache_tests
,
189 stats
->tests
? 100.0 * stats
->cache_tests
/ stats
->tests
: 0);
191 fprintf (file
, _("%u bitset_lists\n"), stats
->lists
);
193 bitset_log_histogram_print (file
, name
, _("count log histogram\n"),
194 BITSET_LOG_COUNT_BINS
, stats
->list_counts
);
196 bitset_log_histogram_print (file
, name
, _("size log histogram\n"),
197 BITSET_LOG_SIZE_BINS
, stats
->list_sizes
);
199 bitset_percent_histogram_print (file
, name
, _("density histogram\n"),
200 BITSET_DENSITY_BINS
, stats
->list_density
);
204 /* Print all bitset statistics to FILE. */
206 bitset_stats_print (FILE *file
, int verbose ATTRIBUTE_UNUSED
)
210 if (!bitset_stats_info
)
213 fprintf (file
, _("Bitset statistics:\n\n"));
215 if (bitset_stats_info
->runs
> 1)
216 fprintf (file
, _("Accumulated runs = %u\n"), bitset_stats_info
->runs
);
218 for (i
= 0; i
< BITSET_TYPE_NUM
; i
++)
219 bitset_stats_print_1 (file
, bitset_type_names
[i
],
220 &bitset_stats_info
->types
[i
]);
224 /* Initialise bitset statistics logging. */
226 bitset_stats_enable (void)
228 if (!bitset_stats_info
)
229 bitset_stats_info
= &bitset_stats_info_data
;
230 bitset_stats_enabled
= 1;
235 bitset_stats_disable (void)
237 bitset_stats_enabled
= 0;
241 /* Read bitset statistics file. */
243 bitset_stats_read (const char *filename
)
247 if (!bitset_stats_info
)
251 filename
= BITSET_STATS_FILE
;
253 file
= fopen (filename
, "r");
256 if (fread (&bitset_stats_info_data
, sizeof (bitset_stats_info_data
),
260 perror (_("Could not read stats file."));
262 fprintf (stderr
, _("Bad stats file size.\n"));
266 bitset_stats_info_data
.runs
++;
270 /* Write bitset statistics file. */
272 bitset_stats_write (const char *filename
)
276 if (!bitset_stats_info
)
280 filename
= BITSET_STATS_FILE
;
282 file
= fopen (filename
, "w");
285 if (fwrite (&bitset_stats_info_data
, sizeof (bitset_stats_info_data
),
287 perror (_("Could not write stats file."));
291 perror (_("Could not open stats file for writing."));
295 /* Dump bitset statistics to FILE. */
297 bitset_stats_dump (FILE *file
)
299 bitset_stats_print (file
, 0);
303 /* Function to be called from debugger to print bitset stats. */
305 debug_bitset_stats (void)
307 bitset_stats_print (stderr
, 1);
312 bitset_stats_set (bitset dst
, bitset_bindex bitno
)
314 bitset bset
= dst
->s
.bset
;
315 bitset_windex wordno
= bitno
/ BITSET_WORD_BITS
;
316 bitset_windex offset
= wordno
- bset
->b
.cindex
;
318 BITSET_STATS_SETS_INC (bset
);
320 if (offset
< bset
->b
.csize
)
322 bset
->b
.cdata
[offset
] |= (bitset_word
) 1 << (bitno
% BITSET_WORD_BITS
);
323 BITSET_STATS_CACHE_SETS_INC (bset
);
326 BITSET_SET_ (bset
, bitno
);
331 bitset_stats_reset (bitset dst
, bitset_bindex bitno
)
333 bitset bset
= dst
->s
.bset
;
334 bitset_windex wordno
= bitno
/ BITSET_WORD_BITS
;
335 bitset_windex offset
= wordno
- bset
->b
.cindex
;
337 BITSET_STATS_RESETS_INC (bset
);
339 if (offset
< bset
->b
.csize
)
341 bset
->b
.cdata
[offset
] &=
342 ~((bitset_word
) 1 << (bitno
% BITSET_WORD_BITS
));
343 BITSET_STATS_CACHE_RESETS_INC (bset
);
346 BITSET_RESET_ (bset
, bitno
);
351 bitset_stats_toggle (bitset src
, bitset_bindex bitno
)
353 return BITSET_TOGGLE_ (src
->s
.bset
, bitno
);
358 bitset_stats_test (bitset src
, bitset_bindex bitno
)
360 bitset bset
= src
->s
.bset
;
361 bitset_windex wordno
= bitno
/ BITSET_WORD_BITS
;
362 bitset_windex offset
= wordno
- bset
->b
.cindex
;
364 BITSET_STATS_TESTS_INC (bset
);
366 if (offset
< bset
->b
.csize
)
368 BITSET_STATS_CACHE_TESTS_INC (bset
);
369 return (bset
->b
.cdata
[offset
] >> (bitno
% BITSET_WORD_BITS
)) & 1;
372 return BITSET_TEST_ (bset
, bitno
);
377 bitset_stats_size (bitset src
)
379 return BITSET_SIZE_ (src
->s
.bset
);
384 bitset_stats_count (bitset src
)
386 return BITSET_COUNT_ (src
->s
.bset
);
391 bitset_stats_empty_p (bitset dst
)
393 return BITSET_EMPTY_P_ (dst
->s
.bset
);
398 bitset_stats_ones (bitset dst
)
400 BITSET_ONES_ (dst
->s
.bset
);
405 bitset_stats_zero (bitset dst
)
407 BITSET_ZERO_ (dst
->s
.bset
);
412 bitset_stats_copy (bitset dst
, bitset src
)
414 BITSET_CHECK2_ (dst
, src
);
415 BITSET_COPY_ (dst
->s
.bset
, src
->s
.bset
);
420 bitset_stats_disjoint_p (bitset dst
, bitset src
)
422 BITSET_CHECK2_ (dst
, src
);
423 return BITSET_DISJOINT_P_ (dst
->s
.bset
, src
->s
.bset
);
428 bitset_stats_equal_p (bitset dst
, bitset src
)
430 BITSET_CHECK2_ (dst
, src
);
431 return BITSET_EQUAL_P_ (dst
->s
.bset
, src
->s
.bset
);
436 bitset_stats_not (bitset dst
, bitset src
)
438 BITSET_CHECK2_ (dst
, src
);
439 BITSET_NOT_ (dst
->s
.bset
, src
->s
.bset
);
444 bitset_stats_subset_p (bitset dst
, bitset src
)
446 BITSET_CHECK2_ (dst
, src
);
447 return BITSET_SUBSET_P_ (dst
->s
.bset
, src
->s
.bset
);
452 bitset_stats_and (bitset dst
, bitset src1
, bitset src2
)
454 BITSET_CHECK3_ (dst
, src1
, src2
);
455 BITSET_AND_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
);
460 bitset_stats_and_cmp (bitset dst
, bitset src1
, bitset src2
)
462 BITSET_CHECK3_ (dst
, src1
, src2
);
463 return BITSET_AND_CMP_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
);
468 bitset_stats_andn (bitset dst
, bitset src1
, bitset src2
)
470 BITSET_CHECK3_ (dst
, src1
, src2
);
471 BITSET_ANDN_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
);
476 bitset_stats_andn_cmp (bitset dst
, bitset src1
, bitset src2
)
478 BITSET_CHECK3_ (dst
, src1
, src2
);
479 return BITSET_ANDN_CMP_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
);
484 bitset_stats_or (bitset dst
, bitset src1
, bitset src2
)
486 BITSET_CHECK3_ (dst
, src1
, src2
);
487 BITSET_OR_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
);
492 bitset_stats_or_cmp (bitset dst
, bitset src1
, bitset src2
)
494 BITSET_CHECK3_ (dst
, src1
, src2
);
495 return BITSET_OR_CMP_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
);
500 bitset_stats_xor (bitset dst
, bitset src1
, bitset src2
)
502 BITSET_CHECK3_ (dst
, src1
, src2
);
503 BITSET_XOR_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
);
508 bitset_stats_xor_cmp (bitset dst
, bitset src1
, bitset src2
)
510 BITSET_CHECK3_ (dst
, src1
, src2
);
511 return BITSET_XOR_CMP_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
);
516 bitset_stats_and_or (bitset dst
, bitset src1
, bitset src2
, bitset src3
)
518 BITSET_CHECK4_ (dst
, src1
, src2
, src3
);
520 BITSET_AND_OR_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
, src3
->s
.bset
);
525 bitset_stats_and_or_cmp (bitset dst
, bitset src1
, bitset src2
, bitset src3
)
527 BITSET_CHECK4_ (dst
, src1
, src2
, src3
);
529 return BITSET_AND_OR_CMP_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
, src3
->s
.bset
);
534 bitset_stats_andn_or (bitset dst
, bitset src1
, bitset src2
, bitset src3
)
536 BITSET_CHECK4_ (dst
, src1
, src2
, src3
);
538 BITSET_ANDN_OR_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
, src3
->s
.bset
);
543 bitset_stats_andn_or_cmp (bitset dst
, bitset src1
, bitset src2
, bitset src3
)
545 BITSET_CHECK4_ (dst
, src1
, src2
, src3
);
547 return BITSET_ANDN_OR_CMP_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
, src3
->s
.bset
);
552 bitset_stats_or_and (bitset dst
, bitset src1
, bitset src2
, bitset src3
)
554 BITSET_CHECK4_ (dst
, src1
, src2
, src3
);
556 BITSET_OR_AND_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
, src3
->s
.bset
);
561 bitset_stats_or_and_cmp (bitset dst
, bitset src1
, bitset src2
, bitset src3
)
563 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
= {
631 bitset_stats_empty_p
,
635 bitset_stats_disjoint_p
,
636 bitset_stats_equal_p
,
638 bitset_stats_subset_p
,
640 bitset_stats_and_cmp
,
642 bitset_stats_andn_cmp
,
646 bitset_stats_xor_cmp
,
648 bitset_stats_and_or_cmp
,
649 bitset_stats_andn_or
,
650 bitset_stats_andn_or_cmp
,
652 bitset_stats_or_and_cmp
,
654 bitset_stats_list_reverse
,
660 /* Return enclosed bitset type. */
662 bitset_stats_type_get (bitset bset
)
664 return BITSET_TYPE_ (bset
->s
.bset
);
669 bitset_stats_bytes (void)
671 return sizeof (struct bitset_stats_struct
);
676 bitset_stats_init (bitset bset
, bitset_bindex n_bits
, enum bitset_type type
)
681 bset
->b
.vtable
= &bitset_stats_vtable
;
688 /* Set up the actual bitset implementation that
689 we are a wrapper over. */
693 bytes
= abitset_bytes (n_bits
);
694 sbset
= (bitset
) xcalloc (1, bytes
);
695 abitset_init (sbset
, n_bits
);
699 bytes
= lbitset_bytes (n_bits
);
700 sbset
= (bitset
) xcalloc (1, bytes
);
701 lbitset_init (sbset
, n_bits
);
705 bytes
= ebitset_bytes (n_bits
);
706 sbset
= (bitset
) xcalloc (1, bytes
);
707 ebitset_init (sbset
, n_bits
);
714 bset
->s
.bset
= sbset
;
716 BITSET_STATS_ALLOCS_INC (type
);