diff --git a/tests/Gperf-simple.c b/tests/Gperf-simple.c index 7d006b1f..dfc66d95 100644 --- a/tests/Gperf-simple.c +++ b/tests/Gperf-simple.c @@ -21,6 +21,7 @@ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +#include #include #include @@ -31,9 +32,15 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #define panic(args...) \ do { fprintf (stderr, args); exit (-1); } while (0) +long dummy; + static long iterations = 10000; static int maxlevel = 100; +#define MB (1024*1024) + +static char big[128*MB]; + static inline double gettime (void) { @@ -44,20 +51,18 @@ gettime (void) } static int -measure_unwind (int maxlevel, double *init, double *step) +measure_unwind (int maxlevel, double *step) { - double stop, mid, start; + double stop, start; unw_cursor_t cursor; unw_context_t uc; int ret, level = 0; - start = gettime (); - unw_getcontext (&uc); if (unw_init_local (&cursor, &uc) < 0) panic ("unw_init_local() failed\n"); - mid = gettime (); + start = gettime (); do { @@ -74,56 +79,99 @@ measure_unwind (int maxlevel, double *init, double *step) panic ("Unwound only %d levels, expected at least %d levels", level, maxlevel); - *init = mid - start; - *step = (stop - mid) / (double) level; + *step = (stop - start) / (double) level; return 0; } static int -f1 (int level, int maxlevel, double *init, double *step) +f1 (int level, int maxlevel, double *step) { if (level == maxlevel) - return measure_unwind (maxlevel, init, step); + return measure_unwind (maxlevel, step); else /* defeat last-call/sibcall optimization */ - return f1 (level + 1, maxlevel, init, step) + level; + return f1 (level + 1, maxlevel, step) + level; } static void doit (const char *label) { - double init, step, min_init, first_init, min_step, first_step; - double sum_init, sum_step; + double step, min_step, first_step, sum_step; int i; - sum_init = sum_step = first_init = first_step = 0.0; - min_init = min_step = 1e99; + sum_step = first_step = 0.0; + min_step = 1e99; for (i = 0; i < iterations; ++i) { - f1 (0, maxlevel, &init, &step); + f1 (0, maxlevel, &step); - sum_init += init; sum_step += step; - if (init < min_init) - min_init = init; if (step < min_step) min_step = step; if (i == 0) - { - first_init = init; - first_step = step; - } + first_step = step; } - printf ("%s:\n" - " unw_{getcontext+init_local}: 1st=%9.3f min=%9.3f avg=%9.3f nsec\n" - " unw_step : 1st=%9.3f min=%9.3f avg=%9.3f nsec\n", - label, - 1e9*first_init, 1e9*min_init, 1e9*sum_init/iterations, + printf ("%s: unw_step : 1st=%9.3f min=%9.3f avg=%9.3f nsec\n", label, 1e9*first_step, 1e9*min_step, 1e9*sum_step/iterations); } +static long +sum (char *buf, size_t size) +{ + long s = 0; + size_t i; + + for (i = 0; i < size; ++i) + s += *buf++; + return s; +} + +static void +measure_init (void) +{ +# define N 1000 + double stop, start, getcontext_cold, getcontext_warm, init_cold, init_warm; + unw_cursor_t cursor[N]; + unw_context_t uc[N]; + int i; + + /* Ensure memory is paged in but not in the cache: */ + memset (cursor, 0, sizeof (cursor)); + memset (uc, 0, sizeof (uc)); + dummy = sum (big, sizeof (big)); + + start = gettime (); + for (i = 0; i < N; ++i) + unw_getcontext (&uc[i]); + stop = gettime (); + getcontext_cold = (stop - start) / N; + + start = gettime (); + for (i = 0; i < N; ++i) + unw_init_local (&cursor[i], &uc[i]); + stop = gettime (); + init_cold = (stop - start) / N; + + start = gettime (); + for (i = 0; i < N; ++i) + unw_getcontext (&uc[0]); + stop = gettime (); + getcontext_warm = (stop - start) / N; + + start = gettime (); + for (i = 0; i < N; ++i) + unw_init_local (&cursor[0], &uc[0]); + stop = gettime (); + init_warm = (stop - start) / N; + + printf ("unw_getcontext : cold avg=%9.3f nsec, warm avg=%9.3f nsec\n", + 1e9 * getcontext_cold, 1e9 * getcontext_warm); + printf ("unw_init_local : cold avg=%9.3f nsec, warm avg=%9.3f nsec\n", + 1e9 * init_cold, 1e9 * init_warm); +} + int main (int argc, char **argv) { @@ -134,14 +182,16 @@ main (int argc, char **argv) iterations = atol (argv[2]); } + measure_init (); + unw_set_caching_policy (unw_local_addr_space, UNW_CACHE_NONE); - doit ("Caching: none"); + doit ("no cache "); unw_set_caching_policy (unw_local_addr_space, UNW_CACHE_GLOBAL); - doit ("Caching: global"); + doit ("global cache "); unw_set_caching_policy (unw_local_addr_space, UNW_CACHE_PER_THREAD); - doit ("Caching: per-thread"); + doit ("per-thread cache"); return 0; }