Commit d4794f25 authored by Yazen Ghannam's avatar Yazen Ghannam Committed by Len Brown

tools/power turbostat: Make interval calculation per thread to reduce jitter

Turbostat currently normalizes TSC and other values by dividing by an
interval. This interval is the delta between the start of one global
(all counters on all CPUs) sampling and the start of another. However,
this introduces a lot of jitter into the data.

In order to reduce jitter, the interval calculation should be based on
timestamps taken per thread and close to the start of the thread's
sampling.

Define a per thread time value to hold the delta between samples taken
on the thread.

Use the timestamp taken at the beginning of sampling to calculate the
delta.

Move the thread's beginning timestamp to after the CPU migration to
avoid jitter due to the migration.

Use the global time delta for the average time delta.
Signed-off-by: default avatarYazen Ghannam <yazen.ghannam@amd.com>
Signed-off-by: default avatarLen Brown <len.brown@intel.com>
parent d743dae6
...@@ -166,6 +166,7 @@ size_t cpu_present_setsize, cpu_affinity_setsize, cpu_subset_size; ...@@ -166,6 +166,7 @@ size_t cpu_present_setsize, cpu_affinity_setsize, cpu_subset_size;
struct thread_data { struct thread_data {
struct timeval tv_begin; struct timeval tv_begin;
struct timeval tv_end; struct timeval tv_end;
struct timeval tv_delta;
unsigned long long tsc; unsigned long long tsc;
unsigned long long aperf; unsigned long long aperf;
unsigned long long mperf; unsigned long long mperf;
...@@ -910,7 +911,7 @@ int format_counters(struct thread_data *t, struct core_data *c, ...@@ -910,7 +911,7 @@ int format_counters(struct thread_data *t, struct core_data *c,
if (DO_BIC(BIC_TOD)) if (DO_BIC(BIC_TOD))
outp += sprintf(outp, "%10ld.%06ld\t", t->tv_end.tv_sec, t->tv_end.tv_usec); outp += sprintf(outp, "%10ld.%06ld\t", t->tv_end.tv_sec, t->tv_end.tv_usec);
interval_float = tv_delta.tv_sec + tv_delta.tv_usec/1000000.0; interval_float = t->tv_delta.tv_sec + t->tv_delta.tv_usec/1000000.0;
tsc = t->tsc * tsc_tweak; tsc = t->tsc * tsc_tweak;
...@@ -1308,6 +1309,7 @@ delta_thread(struct thread_data *new, struct thread_data *old, ...@@ -1308,6 +1309,7 @@ delta_thread(struct thread_data *new, struct thread_data *old,
* over-write old w/ new so we can print end of interval values * over-write old w/ new so we can print end of interval values
*/ */
timersub(&new->tv_begin, &old->tv_begin, &old->tv_delta);
old->tv_begin = new->tv_begin; old->tv_begin = new->tv_begin;
old->tv_end = new->tv_end; old->tv_end = new->tv_end;
...@@ -1403,6 +1405,8 @@ void clear_counters(struct thread_data *t, struct core_data *c, struct pkg_data ...@@ -1403,6 +1405,8 @@ void clear_counters(struct thread_data *t, struct core_data *c, struct pkg_data
t->tv_begin.tv_usec = 0; t->tv_begin.tv_usec = 0;
t->tv_end.tv_sec = 0; t->tv_end.tv_sec = 0;
t->tv_end.tv_usec = 0; t->tv_end.tv_usec = 0;
t->tv_delta.tv_sec = 0;
t->tv_delta.tv_usec = 0;
t->tsc = 0; t->tsc = 0;
t->aperf = 0; t->aperf = 0;
...@@ -1572,6 +1576,9 @@ void compute_average(struct thread_data *t, struct core_data *c, ...@@ -1572,6 +1576,9 @@ void compute_average(struct thread_data *t, struct core_data *c,
for_all_cpus(sum_counters, t, c, p); for_all_cpus(sum_counters, t, c, p);
/* Use the global time delta for the average. */
average.threads.tv_delta = tv_delta;
average.threads.tsc /= topo.num_cpus; average.threads.tsc /= topo.num_cpus;
average.threads.aperf /= topo.num_cpus; average.threads.aperf /= topo.num_cpus;
average.threads.mperf /= topo.num_cpus; average.threads.mperf /= topo.num_cpus;
...@@ -1761,13 +1768,13 @@ int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p) ...@@ -1761,13 +1768,13 @@ int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
struct msr_counter *mp; struct msr_counter *mp;
int i; int i;
gettimeofday(&t->tv_begin, (struct timezone *)NULL);
if (cpu_migrate(cpu)) { if (cpu_migrate(cpu)) {
fprintf(outf, "Could not migrate to CPU %d\n", cpu); fprintf(outf, "Could not migrate to CPU %d\n", cpu);
return -1; return -1;
} }
gettimeofday(&t->tv_begin, (struct timezone *)NULL);
if (first_counter_read) if (first_counter_read)
get_apic_id(t); get_apic_id(t);
retry: retry:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment