From: Julian Seward Date: Mon, 27 Oct 2008 01:25:14 +0000 (+0000) Subject: Speed up VG_(am_find_nsegment). This is kind-of required by r8712, X-Git-Tag: svn/VALGRIND_3_4_0~181 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d658fbf429c3a575aa06c20b5994acbbbb440219;p=thirdparty%2Fvalgrind.git Speed up VG_(am_find_nsegment). This is kind-of required by r8712, which in turn is a fix for #156404. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@8713 --- diff --git a/coregrind/m_aspacemgr/aspacemgr-linux.c b/coregrind/m_aspacemgr/aspacemgr-linux.c index 5f30c96d6b..38c11f7ba5 100644 --- a/coregrind/m_aspacemgr/aspacemgr-linux.c +++ b/coregrind/m_aspacemgr/aspacemgr-linux.c @@ -325,6 +325,7 @@ static Addr aspacem_vStart = 0; /* ------ end of STATE for the address-space manager ------ */ /* ------ Forwards decls ------ */ +inline static Int find_nsegment_idx ( Addr a ); static void parse_procselfmaps ( @@ -1100,8 +1101,19 @@ void ML_(am_do_sanity_check)( void ) /*-----------------------------------------------------------------*/ /* Binary search the interval array for a given address. Since the - array covers the entire address space the search cannot fail. */ -static Int find_nsegment_idx ( Addr a ) + array covers the entire address space the search cannot fail. The + _WRK function does the real work. Its caller (just below) caches + the results thereof, to save time. With N_CACHE of 63 we get a hit + rate exceeding 90% when running OpenOffice. + + Re ">> 12", it doesn't matter that the page size of some targets + might be different from 12. Really "(a >> 12) % N_CACHE" is merely + a hash function, and the actual cache entry is always validated + correctly against the selected cache entry before use. +*/ +/* Don't call find_nsegment_idx_WRK; use find_nsegment_idx instead. */ +__attribute__((noinline)) +static Int find_nsegment_idx_WRK ( Addr a ) { Addr a_mid_lo, a_mid_hi; Int mid, @@ -1125,6 +1137,52 @@ static Int find_nsegment_idx ( Addr a ) } } +inline static Int find_nsegment_idx ( Addr a ) +{ +# define N_CACHE 63 + static Addr cache_pageno[N_CACHE]; + static Int cache_segidx[N_CACHE]; + static Bool cache_inited = False; + + static UWord n_q = 0; + static UWord n_m = 0; + + UWord ix; + + if (LIKELY(cache_inited)) { + /* do nothing */ + } else { + for (ix = 0; ix < N_CACHE; ix++) { + cache_pageno[ix] = 0; + cache_segidx[ix] = -1; + } + cache_inited = True; + } + + ix = (a >> 12) % N_CACHE; + + n_q++; + if (0 && 0 == (n_q & 0xFFFF)) + VG_(debugLog)(0,"xxx","find_nsegment_idx: %lu %lu\n", n_q, n_m); + + if ((a >> 12) == cache_pageno[ix] + && cache_segidx[ix] >= 0 + && cache_segidx[ix] < nsegments_used + && nsegments[cache_segidx[ix]].start <= a + && a <= nsegments[cache_segidx[ix]].end) { + /* hit */ + /* aspacem_assert( cache_segidx[ix] == find_nsegment_idx_WRK(a) ); */ + return cache_segidx[ix]; + } + /* miss */ + n_m++; + cache_segidx[ix] = find_nsegment_idx_WRK(a); + cache_pageno[ix] = a >> 12; + return cache_segidx[ix]; +# undef N_CACHE +} + + /* Finds the segment containing 'a'. Only returns file/anon/resvn segments. This returns a 'NSegment const *' - a pointer to