1 /* Licensed under LGPLv2.1+ - see LICENSE file for details */
2 #ifdef CCAN_LIKELY_DEBUG
3 #include <ccan/likely/likely.h>
4 #include <ccan/hash/hash.h>
5 #include <ccan/htable/htable_type.h>
13 unsigned long count
, right
;
16 static size_t hash_trace(const struct trace
*trace
)
18 return hash(trace
->condstr
, strlen(trace
->condstr
),
19 hash(trace
->file
, strlen(trace
->file
),
20 trace
->line
+ trace
->expect
));
23 static bool trace_eq(const struct trace
*t1
, const struct trace
*t2
)
25 return t1
->condstr
== t2
->condstr
26 && t1
->file
== t2
->file
27 && t1
->line
== t2
->line
28 && t1
->expect
== t2
->expect
;
32 HTABLE_DEFINE_TYPE(struct trace
, (const struct trace
*), hash_trace
, trace_eq
,
35 static struct thash htable
36 = { HTABLE_INITIALIZER(htable
.raw
, thash_hash
, NULL
) };
38 static void init_trace(struct trace
*trace
,
39 const char *condstr
, const char *file
, unsigned int line
,
42 trace
->condstr
= condstr
;
45 trace
->expect
= expect
;
46 trace
->count
= trace
->right
= 0;
49 static struct trace
*add_trace(const struct trace
*t
)
51 struct trace
*trace
= malloc(sizeof(*trace
));
53 thash_add(&htable
, trace
);
57 long _likely_trace(bool cond
, bool expect
,
59 const char *file
, unsigned int line
)
61 struct trace
*p
, trace
;
63 init_trace(&trace
, condstr
, file
, line
, expect
);
64 p
= thash_get(&htable
, &trace
);
66 p
= add_trace(&trace
);
75 static double right_ratio(const struct trace
*t
)
77 return (double)t
->right
/ t
->count
;
80 char *likely_stats(unsigned int min_hits
, unsigned int percent
)
91 /* This is O(n), but it's not likely called that often. */
92 for (t
= thash_first(&htable
, &i
); t
; t
= thash_next(&htable
, &i
)) {
93 if (t
->count
>= min_hits
) {
94 if (right_ratio(t
) < worst_ratio
) {
96 worst_ratio
= right_ratio(t
);
101 if (worst_ratio
* 100 > percent
)
104 ret
= malloc(strlen(worst
->condstr
) +
105 strlen(worst
->file
) +
106 sizeof(long int) * 8 +
107 sizeof("%s:%u:%slikely(%s) correct %u%% (%lu/%lu)"));
108 sprintf(ret
, "%s:%u:%slikely(%s) correct %u%% (%lu/%lu)",
109 worst
->file
, worst
->line
,
110 worst
->expect
? "" : "un", worst
->condstr
,
111 (unsigned)(worst_ratio
* 100),
112 worst
->right
, worst
->count
);
114 thash_del(&htable
, worst
);
120 void likely_stats_reset(void)
125 /* This is a bit better than O(n^2), but we have to loop since
126 * first/next during delete is unreliable. */
127 while ((t
= thash_first(&htable
, &i
)) != NULL
) {
128 for (; t
; t
= thash_next(&htable
, &i
)) {
129 thash_del(&htable
, t
);
134 thash_clear(&htable
);
136 #endif /*CCAN_LIKELY_DEBUG*/