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 /* Configuration macros. */
43 #define BITSET_STATS_FILE "bitset.dat"
44 #define BITSET_LOG_COUNT_BINS 10
45 #define BITSET_LOG_SIZE_BINS 16
46 #define BITSET_DENSITY_BINS 20
49 /* Accessor macros. */
50 #define BITSET_STATS_ALLOCS_INC(TYPE) \
51 bitset_stats_info->types[(TYPE)].allocs++
52 #define BITSET_STATS_FREES_INC(BSET) \
53 bitset_stats_info->types[BITSET_TYPE_ (BSET)].frees++
54 #define BITSET_STATS_SETS_INC(BSET) \
55 bitset_stats_info->types[BITSET_TYPE_ (BSET)].sets++
56 #define BITSET_STATS_CACHE_SETS_INC(BSET) \
57 bitset_stats_info->types[BITSET_TYPE_ (BSET)].cache_sets++
58 #define BITSET_STATS_RESETS_INC(BSET) \
59 bitset_stats_info->types[BITSET_TYPE_ (BSET)].resets++
60 #define BITSET_STATS_CACHE_RESETS_INC(BSET) \
61 bitset_stats_info->types[BITSET_TYPE_ (BSET)].cache_resets++
62 #define BITSET_STATS_TESTS_INC(BSET) \
63 bitset_stats_info->types[BITSET_TYPE_ (BSET)].tests++
64 #define BITSET_STATS_CACHE_TESTS_INC(BSET) \
65 bitset_stats_info->types[BITSET_TYPE_ (BSET)].cache_tests++
66 #define BITSET_STATS_LISTS_INC(BSET) \
67 bitset_stats_info->types[BITSET_TYPE_ (BSET)].lists++
68 #define BITSET_STATS_LIST_COUNTS_INC(BSET, I) \
69 bitset_stats_info->types[BITSET_TYPE_ (BSET)].list_counts[(I)]++
70 #define BITSET_STATS_LIST_SIZES_INC(BSET, I) \
71 bitset_stats_info->types[BITSET_TYPE_ (BSET)].list_sizes[(I)]++
72 #define BITSET_STATS_LIST_DENSITY_INC(BSET, I) \
73 bitset_stats_info->types[BITSET_TYPE_ (BSET)].list_density[(I)]++
76 typedef struct bitset_stats_struct
84 struct bbitset_struct b
;
85 struct bitset_stats_struct s
;
89 struct bitset_type_info_struct
95 unsigned int cache_sets
;
97 unsigned int cache_resets
;
99 unsigned int cache_tests
;
100 unsigned int list_counts
[BITSET_LOG_COUNT_BINS
];
101 unsigned int list_sizes
[BITSET_LOG_SIZE_BINS
];
102 unsigned int list_density
[BITSET_DENSITY_BINS
];
105 struct bitset_stats_info_struct
108 struct bitset_type_info_struct types
[BITSET_TYPE_NUM
];
112 struct bitset_stats_info_struct bitset_stats_info_data
;
113 struct bitset_stats_info_struct
*bitset_stats_info
;
114 int bitset_stats_enabled
= 0;
117 static void bitset_stats_set
PARAMS ((bitset
, bitset_bindex
));
118 static void bitset_stats_reset
PARAMS ((bitset
, bitset_bindex
));
119 static int bitset_stats_test
PARAMS ((bitset
, bitset_bindex
));
120 static int bitset_stats_size
PARAMS ((bitset
));
121 static int bitset_stats_op1
PARAMS ((bitset
, enum bitset_ops
));
122 static int bitset_stats_op2
PARAMS ((bitset
, bitset
, enum bitset_ops
));
123 static int bitset_stats_op3
PARAMS ((bitset
, bitset
, bitset
, enum bitset_ops
));
124 static int bitset_stats_op4
PARAMS ((bitset
, bitset
, bitset
, bitset
,
126 static int bitset_stats_list
PARAMS ((bitset
, bitset_bindex
*, bitset_bindex
,
128 static int bitset_stats_reverse_list
129 PARAMS ((bitset
, bitset_bindex
*, bitset_bindex
, bitset_bindex
*));
130 static void bitset_stats_free
PARAMS ((bitset
));
131 static void bitset_percent_histogram_print
PARAMS ((FILE *, const char *,
135 static void bitset_log_histogram_print
PARAMS ((FILE *, const char *,
139 static void bitset_stats_print_1
140 PARAMS ((FILE *, const char *, struct bitset_type_info_struct
*));
141 static void bitset_stats_print
PARAMS ((FILE *, int));
144 /* Print a percentage histogram with message MSG to FILE. */
146 bitset_percent_histogram_print (file
, name
, msg
, n_bins
, bins
)
157 for (i
= 0; i
< n_bins
; i
++)
163 fprintf (file
, "%s %s", name
, msg
);
164 for (i
= 0; i
< n_bins
; i
++)
165 fprintf (file
, "%.0f-%.0f%%\t%8d (%5.1f%%)\n",
167 (i
+ 1) * 100.0 / n_bins
, bins
[i
],
168 (100.0 * bins
[i
]) / total
);
172 /* Print a log histogram with message MSG to FILE. */
174 bitset_log_histogram_print (file
, name
, msg
, n_bins
, bins
)
183 unsigned int max_width
;
184 unsigned int last_bin
;
187 for (i
= 0; i
< n_bins
; i
++)
193 for (i
= n_bins
; i
> 3 && ! bins
[i
- 1]; i
--)
197 /* 2 * ceil (log10 (2) * (N - 1)) + 1. */
198 max_width
= 2 * (unsigned int) (0.30103 * (n_bins
- 1) + 0.9999) + 1;
200 fprintf (file
, "%s %s", name
, msg
);
201 for (i
= 0; i
< 2; i
++)
202 fprintf (file
, "%*d\t%8d (%5.1f%%)\n",
203 max_width
, i
, bins
[i
], 100.0 * bins
[i
] / total
);
205 for (; i
<= last_bin
; i
++)
206 fprintf (file
, "%*d-%d\t%8d (%5.1f%%)\n",
207 max_width
- ((unsigned int) (0.30103 * (i
) + 0.9999) + 1),
208 1 << (i
- 1), (1 << i
) - 1, bins
[i
],
209 (100.0 * bins
[i
]) / total
);
213 /* Print bitset statistics to FILE. */
215 bitset_stats_print_1 (file
, name
, stats
)
218 struct bitset_type_info_struct
*stats
;
223 fprintf (file
, "%s:\n", name
);
224 fprintf (file
, "%d bitset_allocs, %d freed (%.2f%%).\n",
225 stats
->allocs
, stats
->frees
,
226 stats
->allocs
? 100.0 * stats
->frees
/ stats
->allocs
: 0);
227 fprintf (file
, "%d bitset_sets, %d cached (%.2f%%)\n",
228 stats
->sets
, stats
->cache_sets
,
229 stats
->sets
? 100.0 * stats
->cache_sets
/ stats
->sets
: 0);
230 fprintf (file
, "%d bitset_resets, %d cached (%.2f%%)\n",
231 stats
->resets
, stats
->cache_resets
,
232 stats
->resets
? 100.0 * stats
->cache_resets
/ stats
->resets
: 0);
233 fprintf (file
, "%d bitset_tests, %d cached (%.2f%%)\n",
234 stats
->tests
, stats
->cache_tests
,
235 stats
->tests
? 100.0 * stats
->cache_tests
/ stats
->tests
: 0);
237 fprintf (file
, "%d bitset_lists\n", stats
->lists
);
239 bitset_log_histogram_print (file
, name
, "count log histogram\n",
240 BITSET_LOG_COUNT_BINS
, stats
->list_counts
);
242 bitset_log_histogram_print (file
, name
, "size log histogram\n",
243 BITSET_LOG_SIZE_BINS
, stats
->list_sizes
);
245 bitset_percent_histogram_print (file
, name
, "density histogram\n",
246 BITSET_DENSITY_BINS
, stats
->list_density
);
250 /* Print all bitset statistics to FILE. */
252 bitset_stats_print (file
, verbose
)
254 int verbose ATTRIBUTE_UNUSED
;
257 static const char *names
[] = BITSET_TYPE_NAMES
;
259 if (!bitset_stats_info
)
262 fprintf (file
, "Bitset statistics:\n\n");
264 if (bitset_stats_info
->runs
> 1)
265 fprintf (file
, "Accumulated runs = %d\n", bitset_stats_info
->runs
);
267 for (i
= 0; i
< BITSET_TYPE_NUM
; i
++)
268 bitset_stats_print_1 (file
, names
[i
], &bitset_stats_info
->types
[i
]);
272 /* Initialise bitset statistics logging. */
274 bitset_stats_enable ()
276 if (!bitset_stats_info
)
277 bitset_stats_info
= &bitset_stats_info_data
;
278 bitset_stats_enabled
= 1;
283 bitset_stats_disable ()
285 bitset_stats_enabled
= 0;
289 /* Read bitset statistics file. */
291 bitset_stats_read (filename
)
292 const char *filename
;
296 if (!bitset_stats_info
)
300 filename
= BITSET_STATS_FILE
;
302 file
= fopen (filename
, "r");
305 if (fread (&bitset_stats_info_data
, sizeof (bitset_stats_info_data
),
309 perror ("Could not read stats file.");
311 fprintf (stderr
, "Bad stats file size.\n");
315 bitset_stats_info_data
.runs
++;
319 /* Write bitset statistics file. */
321 bitset_stats_write (filename
)
322 const char *filename
;
326 if (!bitset_stats_info
)
330 filename
= BITSET_STATS_FILE
;
332 file
= fopen (filename
, "w");
335 if (fwrite (&bitset_stats_info_data
, sizeof (bitset_stats_info_data
),
337 perror ("Could not write stats file.");
341 perror ("Could not open stats file for writing.");
345 /* Dump bitset statistics to FILE. */
347 bitset_stats_dump (file
)
350 bitset_stats_print (file
, 0);
354 /* Function to be called from debugger to print bitset stats. */
356 debug_bitset_stats (void)
358 bitset_stats_print (stderr
, 1);
363 bitset_stats_set (dst
, bitno
)
367 bitset bset
= dst
->s
.bset
;
368 bitset_windex index
= bitno
/ BITSET_WORD_BITS
;
369 bitset_windex offset
= index
- bset
->b
.cindex
;
371 BITSET_STATS_SETS_INC (bset
);
373 if (offset
< bset
->b
.csize
)
375 bset
->b
.cdata
[offset
] |= (1 << (bitno
% BITSET_WORD_BITS
));
376 BITSET_STATS_CACHE_SETS_INC (bset
);
379 BITSET_SET_ (bset
, bitno
);
384 bitset_stats_reset (dst
, bitno
)
388 bitset bset
= dst
->s
.bset
;
389 bitset_windex index
= bitno
/ BITSET_WORD_BITS
;
390 bitset_windex offset
= index
- bset
->b
.cindex
;
392 BITSET_STATS_RESETS_INC (bset
);
394 if (offset
< bset
->b
.csize
)
396 bset
->b
.cdata
[offset
] &= ~(1 << (bitno
% BITSET_WORD_BITS
));
397 BITSET_STATS_CACHE_RESETS_INC (bset
);
400 BITSET_RESET_ (bset
, bitno
);
405 bitset_stats_test (src
, bitno
)
409 bitset bset
= src
->s
.bset
;
410 bitset_windex index
= bitno
/ BITSET_WORD_BITS
;
411 bitset_windex offset
= index
- bset
->b
.cindex
;
413 BITSET_STATS_TESTS_INC (bset
);
415 if (offset
< bset
->b
.csize
)
417 BITSET_STATS_CACHE_TESTS_INC (bset
);
418 return (bset
->b
.cdata
[offset
] >> (bitno
% BITSET_WORD_BITS
)) & 1;
421 return BITSET_TEST_ (bset
, bitno
);
426 bitset_stats_size (src
)
429 return BITSET_SIZE_ (src
->s
.bset
);
434 bitset_stats_op1 (dst
, op
)
438 return BITSET_OP1_ (dst
->s
.bset
, op
);
443 bitset_stats_op2 (dst
, src
, op
)
448 BITSET_CHECK2_ (dst
, src
);
449 return BITSET_OP2_ (dst
->s
.bset
, src
->s
.bset
, op
);
454 bitset_stats_op3 (dst
, src1
, src2
, op
)
460 BITSET_CHECK3_ (dst
, src1
, src2
);
461 return BITSET_OP3_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
, op
);
466 bitset_stats_op4 (dst
, src1
, src2
, src3
, op
)
473 BITSET_CHECK4_ (dst
, src1
, src2
, src3
);
475 /* This is a bit of a hack. If the implementation handles
476 a four operand operation then vector to it, passing
477 the enclosed bitsets. Otherwise use the fallback
478 bitset_op4 routine. */
479 if (dst
->s
.bset
->b
.ops
->op4
!= bitset_op4
)
480 return BITSET_OP4_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
,
483 return bitset_op4 (dst
, src1
, src2
, src3
, op
);
488 bitset_stats_list (bset
, list
, num
, next
)
498 enum bitset_type type
;
500 count
= BITSET_LIST_ (bset
->s
.bset
, list
, num
, next
);
502 type
= BITSET_TYPE_ (bset
->s
.bset
);
503 BITSET_STATS_LISTS_INC (bset
->s
.bset
);
505 /* Log histogram of number of set bits. */
506 for (i
= 0, tmp
= count
; tmp
; tmp
>>= 1, i
++)
508 if (i
>= BITSET_LOG_COUNT_BINS
)
509 i
= BITSET_LOG_COUNT_BINS
- 1;
510 BITSET_STATS_LIST_COUNTS_INC (bset
->s
.bset
, i
);
512 /* Log histogram of number of bits in set. */
513 size
= BITSET_SIZE_ (bset
->s
.bset
);
514 for (i
= 0, tmp
= size
; tmp
; tmp
>>= 1, i
++)
516 if (i
>= BITSET_LOG_SIZE_BINS
)
517 i
= BITSET_LOG_SIZE_BINS
- 1;
518 BITSET_STATS_LIST_SIZES_INC (bset
->s
.bset
, i
);
520 /* Histogram of fraction of bits set. */
521 i
= size
? (count
* BITSET_DENSITY_BINS
) / size
: 0;
522 if (i
>= BITSET_DENSITY_BINS
)
523 i
= BITSET_DENSITY_BINS
- 1;
524 BITSET_STATS_LIST_DENSITY_INC (bset
->s
.bset
, i
);
530 bitset_stats_reverse_list (bset
, list
, num
, next
)
536 return BITSET_REVERSE_LIST_ (bset
->s
.bset
, list
, num
, next
);
541 bitset_stats_free (bset
)
544 BITSET_STATS_FREES_INC (bset
->s
.bset
);
545 BITSET_FREE_ (bset
->s
.bset
);
549 struct bitset_ops_struct bitset_stats_ops
= {
559 bitset_stats_reverse_list
,
565 /* Return enclosed bitset type. */
567 bitset_stats_type_get (bset
)
570 return BITSET_TYPE_ (bset
->s
.bset
);
574 int bitset_stats_bytes (void)
576 return sizeof (struct bitset_struct
);
581 bitset_stats_init (bset
, n_bits
, type
)
583 bitset_bindex n_bits
;
584 enum bitset_type type
;
589 bset
->b
.ops
= &bitset_stats_ops
;
596 /* Set up the actual bitset implementation that
597 we are a wrapper over. */
601 bytes
= abitset_bytes (n_bits
);
602 sbset
= (bitset
) xcalloc (1, bytes
);
603 abitset_init (sbset
, n_bits
);
607 bytes
= lbitset_bytes (n_bits
);
608 sbset
= (bitset
) xcalloc (1, bytes
);
609 lbitset_init (sbset
, n_bits
);
613 bytes
= ebitset_bytes (n_bits
);
614 sbset
= (bitset
) xcalloc (1, bytes
);
615 ebitset_init (sbset
, n_bits
);
622 bset
->s
.bset
= sbset
;
624 BITSET_STATS_ALLOCS_INC (type
);