diff options
author | Andy Lutomirski <luto@kernel.org> | 2015-12-07 22:15:00 -0800 |
---|---|---|
committer | Andy Lutomirski <luto@kernel.org> | 2015-12-07 22:15:00 -0800 |
commit | 8f2db24d3becc44b58eb4a46808aeff4d1cdbc18 (patch) | |
tree | 623174972aa32a736bd55245fa5c69bd48b7d54d | |
parent | 6f4d4ea67c8e88a472bc215dde69f1c9279bdafb (diff) | |
download | misc-tests-8f2db24d3becc44b58eb4a46808aeff4d1cdbc18.tar.gz |
perf_self_monitor: Make the number of reps configurable
Merely adding the loop adds about six cycles to ENOSYS.
Signed-off-by: Andy Lutomirski <luto@kernel.org>
-rw-r--r-- | tight_loop/perf_self_monitor.c | 59 |
1 files changed, 38 insertions, 21 deletions
diff --git a/tight_loop/perf_self_monitor.c b/tight_loop/perf_self_monitor.c index 51c3338..323e91f 100644 --- a/tight_loop/perf_self_monitor.c +++ b/tight_loop/perf_self_monitor.c @@ -82,6 +82,7 @@ static inline uint64_t psm_rdpmc(unsigned int ecx) typedef bool (*psm_sample_fn)(uint64_t *count, const struct psm_counter *counter, + int reps, void *opaque); /* @@ -146,40 +147,46 @@ static inline bool psm_atomic_elapsed(uint64_t *elapsed_count, } bool psm_atomic_sample_empty(uint64_t *count, - const struct psm_counter *ctr, void *opaque) + const struct psm_counter *ctr, + int reps, void *opaque) { struct psm_atomic duration = psm_atomic_start(ctr); return psm_atomic_elapsed(count, &duration, ctr); } bool psm_atomic_sample_enosys(uint64_t *count, - const struct psm_counter *ctr, void *opaque) + const struct psm_counter *ctr, + int reps, void *opaque) { struct psm_atomic duration = psm_atomic_start(ctr); #ifdef __x86_64__ unsigned long rax; - rax = 0xbfffffff; - asm volatile ("syscall" : "+a" (rax) : : "rcx", "r11"); + for (int i = 0; i < reps; i++) { + rax = 0xbfffffff; + asm volatile ("syscall" : "+a" (rax) : : "rcx", "r11"); + } #else - syscall(0x3fffffff); + for (int i = 0; i < reps; i++) + syscall(0x3fffffff); #endif return psm_atomic_elapsed(count, &duration, ctr); } -bool psm_atomic_sample_bad_prctl_x1000(uint64_t *count, - const struct psm_counter *ctr, void *opaque) +bool psm_atomic_sample_bad_prctl(uint64_t *count, + const struct psm_counter *ctr, + int reps, void *opaque) { struct psm_atomic duration = psm_atomic_start(ctr); #ifdef __x86_64__ unsigned long rax; register unsigned long rdi asm("rdi"); - for (int i = 0; i < 1000; i++) { + for (int i = 0; i < reps; i++) { rax = SYS_prctl; rdi = -1; asm volatile ("syscall" : "+a" (rax), "+r" (rdi) : : "rcx", "r11"); } #else - for (int i = 0; i < 1000; i++) + for (int i = 0; i < reps; i++) syscall(SYS_prctl, -1); #endif return psm_atomic_elapsed(count, &duration, ctr); @@ -198,7 +205,8 @@ static int compare_ui64(const void *a_void, const void *b_void) } uint64_t psm_integer_quantile(const struct psm_counter *ctr, psm_sample_fn fn, - void *opaque, size_t q, size_t n) + int reps, void *opaque, + size_t q, size_t n) { if (q >= n) abort(); @@ -206,7 +214,7 @@ uint64_t psm_integer_quantile(const struct psm_counter *ctr, psm_sample_fn fn, uint64_t *array = calloc(sizeof(uint64_t), n); for (size_t i = 0; i < n; ) { uint64_t sample; - if (!fn(&sample, ctr, opaque)) + if (!fn(&sample, ctr, reps, opaque)) continue; array[i++] = sample; } @@ -218,7 +226,8 @@ uint64_t psm_integer_quantile(const struct psm_counter *ctr, psm_sample_fn fn, return ret; } -void psm_settle(const struct psm_counter *ctr, psm_sample_fn fn, void *opaque) +void psm_settle(const struct psm_counter *ctr, psm_sample_fn fn, + int reps, void *opaque) { uint64_t val = UINT64_MAX; int good_iters = 0; @@ -226,7 +235,7 @@ void psm_settle(const struct psm_counter *ctr, psm_sample_fn fn, void *opaque) uint64_t best = UINT64_MAX; for (int inner = 0; inner < 10; ) { uint64_t count; - if (!fn(&count, ctr, opaque)) + if (!fn(&count, ctr, reps, opaque)) continue; /* Rejected sample */ if (count < best) best = count; @@ -244,26 +253,34 @@ void psm_settle(const struct psm_counter *ctr, psm_sample_fn fn, void *opaque) } } +int reparray[] = {1, 200}; + int main() { struct psm_counter *ctr = psm_counter_create(); - psm_settle(ctr, psm_atomic_sample_empty, NULL); + psm_settle(ctr, psm_atomic_sample_empty, 1, NULL); uint64_t baseline = psm_integer_quantile(ctr, psm_atomic_sample_empty, - NULL, 250, 500); + 1, NULL, 250, 500); printf("An empty sample takes %llu cycles\n", (unsigned long long)baseline); - for (int i = 0; i < 20; i++) { - uint64_t cost = psm_integer_quantile(ctr, psm_atomic_sample_enosys, NULL, 250, 500) - baseline; - printf("1x ENOSYS: %llu\n", (unsigned long long)cost); + for (int repidx = 0; repidx < 2; repidx++) { + int reps = reparray[repidx]; + for (int i = 0; i < 10; i++) { + uint64_t cost = psm_integer_quantile(ctr, psm_atomic_sample_enosys, reps, NULL, 250, 500) - baseline; + printf("%dx ENOSYS: %llu\n", reps, (unsigned long long)cost/reps); + } } - for (int i = 0; i < 20; i++) { - uint64_t cost = psm_integer_quantile(ctr, psm_atomic_sample_bad_prctl_x1000, NULL, 250, 500) - baseline; - printf("1000x bad prctl: %llu\n", (unsigned long long)cost/1000); + for (int repidx = 0; repidx < 2; repidx++) { + int reps = reparray[repidx]; + for (int i = 0; i < 10; i++) { + uint64_t cost = psm_integer_quantile(ctr, psm_atomic_sample_bad_prctl, reps, NULL, 250, 500) - baseline; + printf("%dx bad prctl: %llu\n", reps, (unsigned long long)cost/reps); + } } psm_counter_destroy(ctr); |