Blob Blame History Raw
commit 149c7022a56e0ffb5fe27681f574d46860323e3c
Author: Anton Blanchard <anton.blanchard@gmail.com>
Date:   Sun Oct 8 21:49:17 2017 -0700

    ppc64_cpu: Scale CPU cycles counter by amount of time it ran
    
    ------=_Part_8274_1145520959.1507524557284
    Content-Type: text/plain; charset="UTF-8"
    
    At the moment we start a CPU cycles counter, sleep one second and
    read the counter value, assuming we got one second of time on the
    PMU.
    
    There are two issues with this. If someone else is consuming all
    the available PMCs, we may end up context switching the PMC and
    count for half (or less) of the time. In this case we report a CPU
    frequency that is half (or less) of what it should be.
    
    On the other hand if the sleep goes for longer than one second which
    might happen on a busy box, then we count for too long and report a
    CPU frequency that is too high.
    
    Also check that we got a reasonable number of cycles and report
    an error if we did not.
    
    Signed-off-by: Anton Blanchard <anton@samba.org>
    
    --
    You received this message because you are subscribed to the Google Groups "Powerpc-utils development mailing list" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to powerpc-utils-devel+unsubscribe@googlegroups.com.
    To post to this group, send email to powerpc-utils-devel@googlegroups.com.
    To view this discussion on the web visit https://groups.google.com/d/msgid/powerpc-utils-devel/6f7e063a-0e51-48fa-a1ae-07b06d3ab8ad%40googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
    
    <div dir="ltr"><div>At the moment we start a CPU cycles counter, sleep one second and</div><div>read the counter value, assuming we got one second of time on the</div><div>PMU.</div><div><br></div><div>There are two issues with this. If someone else is consuming all</div><div>the available PMCs, we may end up context switching the PMC and</div><div>count for half (or less) of the time. In this case we report a CPU</div><div>frequency that is half (or less) of what it should be.</div><div><br></div><div>On the other hand if the sleep goes for longer than one second which</div><div>might happen on a busy box, then we count for too long and report a</div><div>CPU frequency that is too high.</div><div><br></div><div>Also check that we got a reasonable number of cycles and report</div><div>an error if we did not.</div><div><br></div><div>Signed-off-by: Anton Blanchard &lt;anton@samba.org&gt;</div><div><br></div></div>
    
    <p></p>
    
    -- <br />
    You received this message because you are subscribed to the Google Groups &quot;Powerpc-utils development mailing list&quot; group.<br />
    To unsubscribe from this group and stop receiving emails from it, send an email to <a href="mailto:powerpc-utils-devel+unsubscribe@googlegroups.com">powerpc-utils-devel+unsubscribe@googlegroups.com</a>.<br />
    To post to this group, send email to <a href="mailto:powerpc-utils-devel@googlegroups.com">powerpc-utils-devel@googlegroups.com</a>.<br />
    To view this discussion on the web visit <a href="https://groups.google.com/d/msgid/powerpc-utils-devel/6f7e063a-0e51-48fa-a1ae-07b06d3ab8ad%40googlegroups.com?utm_medium=email&utm_source=footer">https://groups.google.com/d/msgid/powerpc-utils-devel/6f7e063a-0e51-48fa-a1ae-07b06d3ab8ad%40googlegroups.com</a>.<br />
    For more options, visit <a href="https://groups.google.com/d/optout">https://groups.google.com/d/optout</a>.<br />
    Signed-off-by: Tyrel Datwyler <tyreld@linux.vnet.ibm.com>

diff --git a/src/ppc64_cpu.c b/src/ppc64_cpu.c
index 87840df..34654b4 100644
--- a/src/ppc64_cpu.c
+++ b/src/ppc64_cpu.c
@@ -64,7 +64,7 @@ struct cpu_freq {
 	int offline;
 	int counter;
 	pthread_t tid;
-	unsigned long long freq;
+	double freq;
 };
 
 #ifndef __NR_perf_event_open
@@ -860,6 +860,9 @@ static int setup_counters(struct cpu_freq *cpu_freqs)
 	attr.disabled = 1;
 	attr.size = sizeof(attr);
 
+	/* Record how long the event ran for */
+	attr.read_format |= PERF_FORMAT_TOTAL_TIME_RUNNING;
+
 	for (i = 0; i < threads_in_system; i++) {
 		if (!cpu_online(i)) {
 			cpu_freqs[i].offline = 1;
@@ -907,9 +910,15 @@ static void stop_counters(struct cpu_freq *cpu_freqs)
 	}
 }
 
+struct read_format {
+	uint64_t value;
+	uint64_t time_running;
+};
+
 static void read_counters(struct cpu_freq *cpu_freqs)
 {
 	int i;
+	struct read_format vals;
 
 	for (i = 0; i < threads_in_system; i++) {
 		size_t res;
@@ -917,9 +926,16 @@ static void read_counters(struct cpu_freq *cpu_freqs)
 		if (cpu_freqs[i].offline)
 			continue;
 
-		res = read(cpu_freqs[i].counter, &cpu_freqs[i].freq,
-			   sizeof(unsigned long long));
-		assert(res == sizeof(unsigned long long));
+		res = read(cpu_freqs[i].counter, &vals, sizeof(vals));
+		assert(res == sizeof(vals));
+
+		/* Warn if we don't get at least 0.1s of time on the CPU */
+		if (vals.time_running < 100000000) {
+			fprintf(stderr, "Measurement interval was too small, is someone running perf?\n");
+			exit(1);
+		}
+
+		cpu_freqs[i].freq = 1.0 * vals.value / vals.time_running;
 
 		close(cpu_freqs[i].counter);
 	}
@@ -1048,16 +1064,14 @@ static void setrlimit_open_files(void)
 	setrlimit(RLIMIT_NOFILE, &new_rlim);
 }
 
-#define freq_calc(cycles, time)	(1.0 * (cycles) / (time) / 1000000000ULL)
-
 static int do_cpu_frequency(int sleep_time)
 {
 	int i, rc;
-	unsigned long long min = -1ULL;
+	double min = -1ULL;
 	unsigned long min_cpu = -1UL;
-	unsigned long long max = 0;
+	double max = 0;
 	unsigned long max_cpu = -1UL;
-	unsigned long long sum = 0;
+	double sum = 0;
 	unsigned long count = 0;
 	struct cpu_freq *cpu_freqs;
 
@@ -1098,7 +1112,7 @@ static int do_cpu_frequency(int sleep_time)
 	read_counters(cpu_freqs);
 
 	for (i = 0; i < threads_in_system; i++) {
-		unsigned long long frequency;
+		double frequency;
 
 		if (cpu_freqs[i].offline)
 			continue;
@@ -1118,11 +1132,9 @@ static int do_cpu_frequency(int sleep_time)
 	}
 
 	report_system_power_mode();
-	printf("min:\t%.3f GHz (cpu %ld)\n", freq_calc(min, sleep_time),
-	       min_cpu);
-	printf("max:\t%.3f GHz (cpu %ld)\n", freq_calc(max, sleep_time),
-	       max_cpu);
-	printf("avg:\t%.3f GHz\n\n", freq_calc((sum / count), sleep_time));
+	printf("min:\t%.3f GHz (cpu %ld)\n", min, min_cpu);
+	printf("max:\t%.3f GHz (cpu %ld)\n", max, max_cpu);
+	printf("avg:\t%.3f GHz\n\n", sum / count);
 
 	free(cpu_freqs);
 	return 0;