summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndy Lutomirski <luto@kernel.org>2015-12-07 22:15:00 -0800
committerAndy Lutomirski <luto@kernel.org>2015-12-07 22:15:00 -0800
commit8f2db24d3becc44b58eb4a46808aeff4d1cdbc18 (patch)
tree623174972aa32a736bd55245fa5c69bd48b7d54d
parent6f4d4ea67c8e88a472bc215dde69f1c9279bdafb (diff)
downloadmisc-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.c59
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);