1 /* CC0 (Public domain) - 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*/