mirror of https://github.com/Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
181 lines
4.8 KiB
181 lines
4.8 KiB
// SPDX-License-Identifier: GPL-2.0-or-later |
|
/* cpufreq-bench CPUFreq microbenchmark |
|
* |
|
* Copyright (C) 2008 Christian Kornacker <[email protected]> |
|
*/ |
|
|
|
#include <stdio.h> |
|
#include <unistd.h> |
|
#include <math.h> |
|
|
|
#include "config.h" |
|
#include "system.h" |
|
#include "benchmark.h" |
|
|
|
/* Print out progress if we log into a file */ |
|
#define show_progress(total_time, progress_time) \ |
|
if (config->output != stdout) { \ |
|
fprintf(stdout, "Progress: %02lu %%\r", \ |
|
(progress_time * 100) / total_time); \ |
|
fflush(stdout); \ |
|
} |
|
|
|
/** |
|
* compute how many rounds of calculation we should do |
|
* to get the given load time |
|
* |
|
* @param load aimed load time in µs |
|
* |
|
* @retval rounds of calculation |
|
**/ |
|
|
|
unsigned int calculate_timespace(long load, struct config *config) |
|
{ |
|
int i; |
|
long long now, then; |
|
unsigned int estimated = GAUGECOUNT; |
|
unsigned int rounds = 0; |
|
unsigned int timed = 0; |
|
|
|
if (config->verbose) |
|
printf("calibrating load of %lius, please wait...\n", load); |
|
|
|
/* get the initial calculation time for a specific number of rounds */ |
|
now = get_time(); |
|
ROUNDS(estimated); |
|
then = get_time(); |
|
|
|
timed = (unsigned int)(then - now); |
|
|
|
/* approximation of the wanted load time by comparing with the |
|
* initial calculation time */ |
|
for (i = 0; i < 4; i++) { |
|
rounds = (unsigned int)(load * estimated / timed); |
|
dprintf("calibrating with %u rounds\n", rounds); |
|
now = get_time(); |
|
ROUNDS(rounds); |
|
then = get_time(); |
|
|
|
timed = (unsigned int)(then - now); |
|
estimated = rounds; |
|
} |
|
if (config->verbose) |
|
printf("calibration done\n"); |
|
|
|
return estimated; |
|
} |
|
|
|
/** |
|
* benchmark |
|
* generates a specific sleep an load time with the performance |
|
* governor and compares the used time for same calculations done |
|
* with the configured powersave governor |
|
* |
|
* @param config config values for the benchmark |
|
* |
|
**/ |
|
|
|
void start_benchmark(struct config *config) |
|
{ |
|
unsigned int _round, cycle; |
|
long long now, then; |
|
long sleep_time = 0, load_time = 0; |
|
long performance_time = 0, powersave_time = 0; |
|
unsigned int calculations; |
|
unsigned long total_time = 0, progress_time = 0; |
|
|
|
sleep_time = config->sleep; |
|
load_time = config->load; |
|
|
|
/* For the progress bar */ |
|
for (_round = 1; _round <= config->rounds; _round++) |
|
total_time += _round * (config->sleep + config->load); |
|
total_time *= 2; /* powersave and performance cycles */ |
|
|
|
for (_round = 0; _round < config->rounds; _round++) { |
|
performance_time = 0LL; |
|
powersave_time = 0LL; |
|
|
|
show_progress(total_time, progress_time); |
|
|
|
/* set the cpufreq governor to "performance" which disables |
|
* P-State switching. */ |
|
if (set_cpufreq_governor("performance", config->cpu) != 0) |
|
return; |
|
|
|
/* calibrate the calculation time. the resulting calculation |
|
* _rounds should produce a load which matches the configured |
|
* load time */ |
|
calculations = calculate_timespace(load_time, config); |
|
|
|
if (config->verbose) |
|
printf("_round %i: doing %u cycles with %u calculations" |
|
" for %lius\n", _round + 1, config->cycles, |
|
calculations, load_time); |
|
|
|
fprintf(config->output, "%u %li %li ", |
|
_round, load_time, sleep_time); |
|
|
|
if (config->verbose) |
|
printf("average: %lius, rps:%li\n", |
|
load_time / calculations, |
|
1000000 * calculations / load_time); |
|
|
|
/* do some sleep/load cycles with the performance governor */ |
|
for (cycle = 0; cycle < config->cycles; cycle++) { |
|
now = get_time(); |
|
usleep(sleep_time); |
|
ROUNDS(calculations); |
|
then = get_time(); |
|
performance_time += then - now - sleep_time; |
|
if (config->verbose) |
|
printf("performance cycle took %lius, " |
|
"sleep: %lius, " |
|
"load: %lius, rounds: %u\n", |
|
(long)(then - now), sleep_time, |
|
load_time, calculations); |
|
} |
|
fprintf(config->output, "%li ", |
|
performance_time / config->cycles); |
|
|
|
progress_time += sleep_time + load_time; |
|
show_progress(total_time, progress_time); |
|
|
|
/* set the powersave governor which activates P-State switching |
|
* again */ |
|
if (set_cpufreq_governor(config->governor, config->cpu) != 0) |
|
return; |
|
|
|
/* again, do some sleep/load cycles with the |
|
* powersave governor */ |
|
for (cycle = 0; cycle < config->cycles; cycle++) { |
|
now = get_time(); |
|
usleep(sleep_time); |
|
ROUNDS(calculations); |
|
then = get_time(); |
|
powersave_time += then - now - sleep_time; |
|
if (config->verbose) |
|
printf("powersave cycle took %lius, " |
|
"sleep: %lius, " |
|
"load: %lius, rounds: %u\n", |
|
(long)(then - now), sleep_time, |
|
load_time, calculations); |
|
} |
|
|
|
progress_time += sleep_time + load_time; |
|
|
|
/* compare the average sleep/load cycles */ |
|
fprintf(config->output, "%li ", |
|
powersave_time / config->cycles); |
|
fprintf(config->output, "%.3f\n", |
|
performance_time * 100.0 / powersave_time); |
|
fflush(config->output); |
|
|
|
if (config->verbose) |
|
printf("performance is at %.2f%%\n", |
|
performance_time * 100.0 / powersave_time); |
|
|
|
sleep_time += config->sleep_step; |
|
load_time += config->load_step; |
|
} |
|
}
|
|
|