Merge r6134:
Accumulate statistics about the number of searches in the errors and
suppressions lists, and rearrange the suppressions list when searching
to reduce cost of future searches.
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@6271 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/m_errormgr.c b/coregrind/m_errormgr.c
index cb71883..205de7c 100644
--- a/coregrind/m_errormgr.c
+++ b/coregrind/m_errormgr.c
@@ -68,7 +68,8 @@
static Error* errors = NULL;
/* The list of suppression directives, as read from the specified
- suppressions file. */
+ suppressions file. Note that the list gets rearranged as a result
+ of the searches done by is_suppressible_error(). */
static Supp* suppressions = NULL;
/* Running count of unsuppressed errors detected. */
@@ -82,6 +83,20 @@
static ThreadId last_tid_printed = 1;
+/* Stats: number of searches of the error list initiated. */
+static UWord em_errlist_searches = 0;
+
+/* Stats: number of comparisons done during error list
+ searching. */
+static UWord em_errlist_cmps = 0;
+
+/* Stats: number of searches of the suppression list initiated. */
+static UWord em_supplist_searches = 0;
+
+/* Stats: number of comparisons done during suppression list
+ searching. */
+static UWord em_supplist_cmps = 0;
+
/*------------------------------------------------------------*/
/*--- Error type ---*/
/*------------------------------------------------------------*/
@@ -532,9 +547,11 @@
construct_error ( &err, tid, ekind, a, s, extra, NULL );
/* First, see if we've got an error record matching this one. */
- p = errors;
- p_prev = NULL;
+ em_errlist_searches++;
+ p = errors;
+ p_prev = NULL;
while (p != NULL) {
+ em_errlist_cmps++;
if (eq_Error(exe_res, p, &err)) {
/* Found it. */
p->count++;
@@ -692,7 +709,7 @@
" </pair>",
su->count, su->sname);
} else {
- VG_(message)(Vg_DebugMsg, "supp: %4d %s", su->count, su->sname);
+ VG_(message)(Vg_DebugMsg, "supp: %6d %s", su->count, su->sname);
}
}
@@ -818,6 +835,34 @@
/*--- Standard suppressions ---*/
/*------------------------------------------------------------*/
+/* Get the next char from fd into *out_buf. Returns 1 if success,
+ 0 if eof or < 0 if error. */
+
+static Int get_char ( Int fd, Char* out_buf )
+{
+ Int r;
+ static Char buf[64];
+ static Int buf_size = 0;
+ static Int buf_used = 0;
+ vg_assert(buf_size >= 0 && buf_size <= 64);
+ vg_assert(buf_used >= 0 && buf_used <= buf_size);
+ if (buf_used == buf_size) {
+ r = VG_(read)(fd, buf, 64);
+ if (r < 0) return r; /* read failed */
+ vg_assert(r >= 0 && r <= 64);
+ buf_size = r;
+ buf_used = 0;
+ }
+ if (buf_size == 0)
+ return 0; /* eof */
+ vg_assert(buf_size >= 0 && buf_size <= 64);
+ vg_assert(buf_used >= 0 && buf_used < buf_size);
+ *out_buf = buf[buf_used];
+ buf_used++;
+ return 1;
+}
+
+
/* Get a non-blank, non-comment line of at most nBuf chars from fd.
Skips leading spaces on the line. Return True if EOF was hit instead.
*/
@@ -828,17 +873,17 @@
while (True) {
/* First, read until a non-blank char appears. */
while (True) {
- n = VG_(read)(fd, &ch, 1);
+ n = get_char(fd, &ch);
if (n == 1 && !VG_(isspace)(ch)) break;
- if (n == 0) return True;
+ if (n <= 0) return True;
}
/* Now, read the line into buf. */
i = 0;
buf[i++] = ch; buf[i] = 0;
while (True) {
- n = VG_(read)(fd, &ch, 1);
- if (n == 0) return False; /* the next call will return True */
+ n = get_char(fd, &ch);
+ if (n <= 0) return False; /* the next call will return True */
if (ch == '\n') break;
if (i > 0 && i == nBuf-1) i--;
buf[i++] = ch; buf[i] = 0;
@@ -920,7 +965,7 @@
filename );
VG_(exit)(1);
}
- fd = sres.val;
+ fd = sres.res;
# define BOMB(S) { err_str = S; goto syntax_error; }
@@ -1137,18 +1182,45 @@
static Supp* is_suppressible_error ( Error* err )
{
Supp* su;
+ Supp* su_prev;
+
+ /* stats gathering */
+ em_supplist_searches++;
/* See if the error context matches any suppression. */
+ su_prev = NULL;
for (su = suppressions; su != NULL; su = su->next) {
- if (supp_matches_error(su, err) &&
- supp_matches_callers(err, su))
- {
+ em_supplist_cmps++;
+ if (supp_matches_error(su, err) && supp_matches_callers(err, su)) {
+ /* got a match. Move this entry to the head of the list
+ in the hope of making future searches cheaper. */
+ if (su_prev) {
+ vg_assert(su_prev->next == su);
+ su_prev->next = su->next;
+ su->next = suppressions;
+ suppressions = su;
+ }
return su;
}
+ su_prev = su;
}
return NULL; /* no matches */
}
+/* Show accumulated error-list and suppression-list search stats.
+*/
+void VG_(print_errormgr_stats) ( void )
+{
+ VG_(message)(Vg_DebugMsg,
+ " errormgr: %,lu supplist searches, %,lu comparisons during search",
+ em_supplist_searches, em_supplist_cmps
+ );
+ VG_(message)(Vg_DebugMsg,
+ " errormgr: %,lu errlist searches, %,lu comparisons during search",
+ em_errlist_searches, em_errlist_cmps
+ );
+}
+
/*--------------------------------------------------------------------*/
/*--- end ---*/
/*--------------------------------------------------------------------*/