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_test
PARAMS ((bitset
, bitset_bindex
));
122 static int bitset_stats_size
PARAMS ((bitset
));
123 static int bitset_stats_op1
PARAMS ((bitset
, enum bitset_ops
));
124 static int bitset_stats_op2
PARAMS ((bitset
, bitset
, enum bitset_ops
));
125 static int bitset_stats_op3
PARAMS ((bitset
, bitset
, bitset
, enum bitset_ops
));
126 static int bitset_stats_op4
PARAMS ((bitset
, bitset
, bitset
, bitset
,
128 static int bitset_stats_list
PARAMS ((bitset
, bitset_bindex
*, bitset_bindex
,
130 static int bitset_stats_reverse_list
131 PARAMS ((bitset
, bitset_bindex
*, bitset_bindex
, bitset_bindex
*));
132 static void bitset_stats_free
PARAMS ((bitset
));
133 static void bitset_percent_histogram_print
PARAMS ((FILE *, const char *,
137 static void bitset_log_histogram_print
PARAMS ((FILE *, const char *,
141 static void bitset_stats_print_1
142 PARAMS ((FILE *, const char *, struct bitset_type_info_struct
*));
143 static void bitset_stats_print
PARAMS ((FILE *, int));
146 /* Print a percentage histogram with message MSG to FILE. */
148 bitset_percent_histogram_print (file
, name
, msg
, n_bins
, bins
)
159 for (i
= 0; i
< n_bins
; i
++)
165 fprintf (file
, "%s %s", name
, msg
);
166 for (i
= 0; i
< n_bins
; i
++)
167 fprintf (file
, "%.0f-%.0f%%\t%8d (%5.1f%%)\n",
169 (i
+ 1) * 100.0 / n_bins
, bins
[i
],
170 (100.0 * bins
[i
]) / total
);
174 /* Print a log histogram with message MSG to FILE. */
176 bitset_log_histogram_print (file
, name
, msg
, n_bins
, bins
)
185 unsigned int max_width
;
186 unsigned int last_bin
;
189 for (i
= 0; i
< n_bins
; i
++)
195 for (i
= n_bins
; i
> 3 && ! bins
[i
- 1]; i
--)
199 /* 2 * ceil (log10 (2) * (N - 1)) + 1. */
200 max_width
= 2 * (unsigned int) (0.30103 * (n_bins
- 1) + 0.9999) + 1;
202 fprintf (file
, "%s %s", name
, msg
);
203 for (i
= 0; i
< 2; i
++)
204 fprintf (file
, "%*d\t%8d (%5.1f%%)\n",
205 max_width
, i
, bins
[i
], 100.0 * bins
[i
] / total
);
207 for (; i
<= last_bin
; i
++)
208 fprintf (file
, "%*d-%d\t%8d (%5.1f%%)\n",
209 max_width
- ((unsigned int) (0.30103 * (i
) + 0.9999) + 1),
210 1 << (i
- 1), (1 << i
) - 1, bins
[i
],
211 (100.0 * bins
[i
]) / total
);
215 /* Print bitset statistics to FILE. */
217 bitset_stats_print_1 (file
, name
, stats
)
220 struct bitset_type_info_struct
*stats
;
225 fprintf (file
, "%s:\n", name
);
226 fprintf (file
, _("%d bitset_allocs, %d freed (%.2f%%).\n"),
227 stats
->allocs
, stats
->frees
,
228 stats
->allocs
? 100.0 * stats
->frees
/ stats
->allocs
: 0);
229 fprintf (file
, _("%d bitset_sets, %d cached (%.2f%%)\n"),
230 stats
->sets
, stats
->cache_sets
,
231 stats
->sets
? 100.0 * stats
->cache_sets
/ stats
->sets
: 0);
232 fprintf (file
, _("%d bitset_resets, %d cached (%.2f%%)\n"),
233 stats
->resets
, stats
->cache_resets
,
234 stats
->resets
? 100.0 * stats
->cache_resets
/ stats
->resets
: 0);
235 fprintf (file
, _("%d bitset_tests, %d cached (%.2f%%)\n"),
236 stats
->tests
, stats
->cache_tests
,
237 stats
->tests
? 100.0 * stats
->cache_tests
/ stats
->tests
: 0);
239 fprintf (file
, _("%d bitset_lists\n"), stats
->lists
);
241 bitset_log_histogram_print (file
, name
, _("count log histogram\n"),
242 BITSET_LOG_COUNT_BINS
, stats
->list_counts
);
244 bitset_log_histogram_print (file
, name
, _("size log histogram\n"),
245 BITSET_LOG_SIZE_BINS
, stats
->list_sizes
);
247 bitset_percent_histogram_print (file
, name
, _("density histogram\n"),
248 BITSET_DENSITY_BINS
, stats
->list_density
);
252 /* Print all bitset statistics to FILE. */
254 bitset_stats_print (file
, verbose
)
256 int verbose ATTRIBUTE_UNUSED
;
259 static const char *names
[] = BITSET_TYPE_NAMES
;
261 if (!bitset_stats_info
)
264 fprintf (file
, _("Bitset statistics:\n\n"));
266 if (bitset_stats_info
->runs
> 1)
267 fprintf (file
, _("Accumulated runs = %d\n"), bitset_stats_info
->runs
);
269 for (i
= 0; i
< BITSET_TYPE_NUM
; i
++)
270 bitset_stats_print_1 (file
, names
[i
], &bitset_stats_info
->types
[i
]);
274 /* Initialise bitset statistics logging. */
276 bitset_stats_enable ()
278 if (!bitset_stats_info
)
279 bitset_stats_info
= &bitset_stats_info_data
;
280 bitset_stats_enabled
= 1;
285 bitset_stats_disable ()
287 bitset_stats_enabled
= 0;
291 /* Read bitset statistics file. */
293 bitset_stats_read (filename
)
294 const char *filename
;
298 if (!bitset_stats_info
)
302 filename
= BITSET_STATS_FILE
;
304 file
= fopen (filename
, "r");
307 if (fread (&bitset_stats_info_data
, sizeof (bitset_stats_info_data
),
311 perror (_("Could not read stats file."));
313 fprintf (stderr
, _("Bad stats file size.\n"));
317 bitset_stats_info_data
.runs
++;
321 /* Write bitset statistics file. */
323 bitset_stats_write (filename
)
324 const char *filename
;
328 if (!bitset_stats_info
)
332 filename
= BITSET_STATS_FILE
;
334 file
= fopen (filename
, "w");
337 if (fwrite (&bitset_stats_info_data
, sizeof (bitset_stats_info_data
),
339 perror (_("Could not write stats file."));
343 perror (_("Could not open stats file for writing."));
347 /* Dump bitset statistics to FILE. */
349 bitset_stats_dump (file
)
352 bitset_stats_print (file
, 0);
356 /* Function to be called from debugger to print bitset stats. */
358 debug_bitset_stats (void)
360 bitset_stats_print (stderr
, 1);
365 bitset_stats_set (dst
, bitno
)
369 bitset bset
= dst
->s
.bset
;
370 bitset_windex wordno
= bitno
/ BITSET_WORD_BITS
;
371 bitset_windex offset
= wordno
- bset
->b
.cindex
;
373 BITSET_STATS_SETS_INC (bset
);
375 if (offset
< bset
->b
.csize
)
377 bset
->b
.cdata
[offset
] |= (bitset_word
) 1 << (bitno
% BITSET_WORD_BITS
);
378 BITSET_STATS_CACHE_SETS_INC (bset
);
381 BITSET_SET_ (bset
, bitno
);
386 bitset_stats_reset (dst
, bitno
)
390 bitset bset
= dst
->s
.bset
;
391 bitset_windex wordno
= bitno
/ BITSET_WORD_BITS
;
392 bitset_windex offset
= wordno
- bset
->b
.cindex
;
394 BITSET_STATS_RESETS_INC (bset
);
396 if (offset
< bset
->b
.csize
)
398 bset
->b
.cdata
[offset
] &=
399 ~((bitset_word
) 1 << (bitno
% BITSET_WORD_BITS
));
400 BITSET_STATS_CACHE_RESETS_INC (bset
);
403 BITSET_RESET_ (bset
, bitno
);
408 bitset_stats_test (src
, bitno
)
412 bitset bset
= src
->s
.bset
;
413 bitset_windex wordno
= bitno
/ BITSET_WORD_BITS
;
414 bitset_windex offset
= wordno
- bset
->b
.cindex
;
416 BITSET_STATS_TESTS_INC (bset
);
418 if (offset
< bset
->b
.csize
)
420 BITSET_STATS_CACHE_TESTS_INC (bset
);
421 return (bset
->b
.cdata
[offset
] >> (bitno
% BITSET_WORD_BITS
)) & 1;
424 return BITSET_TEST_ (bset
, bitno
);
429 bitset_stats_size (src
)
432 return BITSET_SIZE_ (src
->s
.bset
);
437 bitset_stats_op1 (dst
, op
)
441 return BITSET_OP1_ (dst
->s
.bset
, op
);
446 bitset_stats_op2 (dst
, src
, op
)
451 BITSET_CHECK2_ (dst
, src
);
452 return BITSET_OP2_ (dst
->s
.bset
, src
->s
.bset
, op
);
457 bitset_stats_op3 (dst
, src1
, src2
, op
)
463 BITSET_CHECK3_ (dst
, src1
, src2
);
464 return BITSET_OP3_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
, op
);
469 bitset_stats_op4 (dst
, src1
, src2
, src3
, op
)
476 BITSET_CHECK4_ (dst
, src1
, src2
, src3
);
478 /* This is a bit of a hack. If the implementation handles
479 a four operand operation then vector to it, passing
480 the enclosed bitsets. Otherwise use the fallback
481 bitset_op4 routine. */
482 if (dst
->s
.bset
->b
.ops
->op4
!= bitset_op4
)
483 return BITSET_OP4_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
,
486 return bitset_op4 (dst
, src1
, src2
, src3
, op
);
491 bitset_stats_list (bset
, list
, num
, next
)
501 enum bitset_type type
;
503 count
= BITSET_LIST_ (bset
->s
.bset
, list
, num
, next
);
505 type
= BITSET_TYPE_ (bset
->s
.bset
);
506 BITSET_STATS_LISTS_INC (bset
->s
.bset
);
508 /* Log histogram of number of set bits. */
509 for (i
= 0, tmp
= count
; tmp
; tmp
>>= 1, i
++)
511 if (i
>= BITSET_LOG_COUNT_BINS
)
512 i
= BITSET_LOG_COUNT_BINS
- 1;
513 BITSET_STATS_LIST_COUNTS_INC (bset
->s
.bset
, i
);
515 /* Log histogram of number of bits in set. */
516 size
= BITSET_SIZE_ (bset
->s
.bset
);
517 for (i
= 0, tmp
= size
; tmp
; tmp
>>= 1, i
++)
519 if (i
>= BITSET_LOG_SIZE_BINS
)
520 i
= BITSET_LOG_SIZE_BINS
- 1;
521 BITSET_STATS_LIST_SIZES_INC (bset
->s
.bset
, i
);
523 /* Histogram of fraction of bits set. */
524 i
= size
? (count
* BITSET_DENSITY_BINS
) / size
: 0;
525 if (i
>= BITSET_DENSITY_BINS
)
526 i
= BITSET_DENSITY_BINS
- 1;
527 BITSET_STATS_LIST_DENSITY_INC (bset
->s
.bset
, i
);
533 bitset_stats_reverse_list (bset
, list
, num
, next
)
539 return BITSET_REVERSE_LIST_ (bset
->s
.bset
, list
, num
, next
);
544 bitset_stats_free (bset
)
547 BITSET_STATS_FREES_INC (bset
->s
.bset
);
548 BITSET_FREE_ (bset
->s
.bset
);
552 struct bitset_ops_struct bitset_stats_ops
= {
562 bitset_stats_reverse_list
,
568 /* Return enclosed bitset type. */
570 bitset_stats_type_get (bset
)
573 return BITSET_TYPE_ (bset
->s
.bset
);
577 int bitset_stats_bytes (void)
579 return sizeof (struct bitset_struct
);
584 bitset_stats_init (bset
, n_bits
, type
)
586 bitset_bindex n_bits
;
587 enum bitset_type type
;
592 bset
->b
.ops
= &bitset_stats_ops
;
599 /* Set up the actual bitset implementation that
600 we are a wrapper over. */
604 bytes
= abitset_bytes (n_bits
);
605 sbset
= (bitset
) xcalloc (1, bytes
);
606 abitset_init (sbset
, n_bits
);
610 bytes
= lbitset_bytes (n_bits
);
611 sbset
= (bitset
) xcalloc (1, bytes
);
612 lbitset_init (sbset
, n_bits
);
616 bytes
= ebitset_bytes (n_bits
);
617 sbset
= (bitset
) xcalloc (1, bytes
);
618 ebitset_init (sbset
, n_bits
);
625 bset
->s
.bset
= sbset
;
627 BITSET_STATS_ALLOCS_INC (type
);