37 #if defined(ENABLE_CYCLES_STATS)
47 struct cycles_stats_percentile {
52 static struct cycles_stats_percentile cycles_stats_percentile_defs[] = {
53 { 10,
"10%-percentile" },
55 { 90,
"90%-percentile" },
56 { 99,
"99%-percentile" },
60 static double cycles_stats_cpu_MHz = 0.0;
62 #define CYCLES_STATS_MAXLINE 100
64 static double cycles_stats_get_cpu_MHz(
void)
67 char line[CYCLES_STATS_MAXLINE + 1];
69 if (cycles_stats_cpu_MHz != 0.0)
70 return cycles_stats_cpu_MHz;
72 info = fopen(
"/proc/cpuinfo",
"r");
74 fprintf(
log_get_logfile(),
"error: could not open /proc/cpuinfo: %s\n",strerror(errno));
78 while (!feof(info) && !ferror(info)) {
79 if (fgets(line,CYCLES_STATS_MAXLINE,info)
80 && sscanf(line,
"cpu MHz : %lf",&cycles_stats_cpu_MHz) == 1)
83 fprintf(
log_get_logfile(),
"CPU frequency used for statistics: %f MHz\n",
84 cycles_stats_cpu_MHz);
85 return cycles_stats_cpu_MHz;
90 fprintf(
log_get_logfile(),
"error reading /proc/cpuinfo: %s\n",strerror(errno));
96 fprintf(
log_get_logfile(),
"warning: falling back to default CPU frequency for statistics\n");
97 cycles_stats_cpu_MHz = 1800.0;
98 return cycles_stats_cpu_MHz;
101 u8 cycles_stats_measurement_overhead = 0;
103 static void cycles_stats_print_percentile(FILE *file,
const char *
name,
104 double percentile,
u8 count,
105 u8 cumul,
double cumulcycles,
106 bool isoverhead,
bool printforall)
109 double cpuMHz = cycles_stats_get_cpu_MHz();
110 u8 cycles_per_ms = cpuMHz * 1000;
113 fprintf(file,
"\t\t%14s = %6.1f\n", name, percentile);
116 percentile -= cycles_stats_measurement_overhead;
118 fprintf(file,
"\t\t%14s = %14.1f (+%llu)",
120 (
unsigned long long)cycles_stats_measurement_overhead);
122 forall = cumulcycles - cumul * cycles_stats_measurement_overhead
123 + percentile * (count - cumul);
124 fprintf(file,
" (%-23s: %15llu cycles = %6lu msec)",
125 (count == cumul) ?
"total" :
"capped here & extrapol.",
126 (
unsigned long long)forall,
127 (
unsigned long)(forall / cycles_per_ms));
133 void cycles_stats_print(FILE *file,
134 const char *name,
int nbins,
int div,
139 struct cycles_stats_percentile *pcd;
145 double cpuMHz = cycles_stats_get_cpu_MHz();
146 u8 cycles_per_ms = cpuMHz * 1000;
148 fprintf(file,
"\t%s: %llu calls\n",
149 (overhead) ?
"measurement overhead determined by" : name,
150 (
unsigned long long)count);
152 fprintf(file,
"\t%s cycles distribution:\n",
153 (overhead) ?
"measurement overhead" : name);
155 cycles_stats_print_percentile(file,
"min", min, count, 0, 0, overhead,
true);
157 pcd = cycles_stats_percentile_defs;
158 for (; pcd->name; pcd++) {
159 floor = (count * pcd->pct) / 100;
160 ceiling = (count * pcd->pct + 99) / 100;
166 assert( ceiling <= floor + 1 );
168 for (i=0; i<nbins; ++
i) {
174 if (floor == cumul && floor == ceiling) {
181 if (cumul <= floor && ceiling <= cumul + bins[i]) {
182 percentile = p + (double)div/2.0;
189 cumulcycles += bins[
i] * (p - (double)div/2.0);
196 if (floor == cumul && floor == ceiling) {
200 if (percentile >= 0) {
201 if (overhead && pcd->pct == 50) {
202 cycles_stats_measurement_overhead = percentile;
204 cycles_stats_print_percentile(file, pcd->name, percentile,
205 count, cumul, cumulcycles,
210 p -= cycles_stats_measurement_overhead;
211 fprintf(file,
"\t\t%14s = unknown (> %llu)\n", pcd->name, (
unsigned long long)p);
215 cycles_stats_print_percentile(file,
"max", max, count, count,
216 total, overhead,
true);
219 fprintf(file,
"\t\t(assuming %llu cycles per ms)\n",
220 (
unsigned long long)cycles_per_ms);
221 fprintf(file,
"\t\t(assuming %llu cycles measurement overhead)\n",
222 (
unsigned long long)cycles_stats_measurement_overhead);
228 for (i=0; i<nbins; ++
i) {
230 fprintf(file,
"\t\t< %8d: %10lu (%3d%%) %10lu\n",
232 (
unsigned long) cumul,
233 (count) ? (
int)((cumul * 100) / count) : 0,
234 (
unsigned long) bins[i]);
237 fprintf(file,
"\t\t>= %8d: %10s (----) %10lu\n",
240 (
unsigned long) bins[nbins]);
JNIEnv jclass jobject const char * name