mirror of
https://github.com/freebsd/freebsd-src.git
synced 2024-12-04 10:19:26 +00:00
Add support for recording the total energy used (in joules) when in
verbose mode. This is useful for profiling new adaptive algorithms in performance (via time(1)) and total energy consumed for a given workload.
This commit is contained in:
parent
7e266fcd1f
commit
ab19351c39
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=144873
@ -30,6 +30,7 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#include <err.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@ -69,10 +70,11 @@ const char *modes[] = {
|
||||
#define APMDEV "/dev/apm"
|
||||
|
||||
static int read_usage_times(long *idle, long *total);
|
||||
static int read_freqs(int *numfreqs, int **freqs);
|
||||
static int read_freqs(int *numfreqs, int **freqs, int **power);
|
||||
static int set_freq(int freq);
|
||||
static void acline_init(void);
|
||||
static int acline_read(void);
|
||||
static void handle_sigs(int sig);
|
||||
static void parse_mode(char *arg, int *mode, int ch);
|
||||
static void usage(void);
|
||||
|
||||
@ -88,6 +90,7 @@ static int cpu_idle_mark;
|
||||
static int poll_ival;
|
||||
|
||||
static int apm_fd;
|
||||
static int exit_requested;
|
||||
|
||||
static int
|
||||
read_usage_times(long *idle, long *total)
|
||||
@ -116,7 +119,7 @@ read_usage_times(long *idle, long *total)
|
||||
}
|
||||
|
||||
static int
|
||||
read_freqs(int *numfreqs, int **freqs)
|
||||
read_freqs(int *numfreqs, int **freqs, int **power)
|
||||
{
|
||||
char *freqstr, *p, *q;
|
||||
int i;
|
||||
@ -138,13 +141,19 @@ read_freqs(int *numfreqs, int **freqs)
|
||||
free(freqstr);
|
||||
return (-1);
|
||||
}
|
||||
if ((*power = malloc(*numfreqs * sizeof(int))) == NULL) {
|
||||
free(freqstr);
|
||||
free(*freqs);
|
||||
return (-1);
|
||||
}
|
||||
for (i = 0, p = freqstr; i < *numfreqs; i++) {
|
||||
q = strchr(p, ' ');
|
||||
if (q != NULL)
|
||||
*q = '\0';
|
||||
if (sscanf(p, "%d/%*d", &(*freqs)[i]) != 1) {
|
||||
if (sscanf(p, "%d/%d", &(*freqs)[i], &(*power)[i]) != 2) {
|
||||
free(freqstr);
|
||||
free(*freqs);
|
||||
free(*power);
|
||||
return (-1);
|
||||
}
|
||||
p = q + 1;
|
||||
@ -224,6 +233,12 @@ parse_mode(char *arg, int *mode, int ch)
|
||||
errx(1, "bad option: -%c %s", (char)ch, optarg);
|
||||
}
|
||||
|
||||
static void
|
||||
handle_sigs(int __unused sig)
|
||||
{
|
||||
exit_requested = 1;
|
||||
}
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
@ -237,8 +252,9 @@ int
|
||||
main(int argc, char * argv[])
|
||||
{
|
||||
long idle, total;
|
||||
int curfreq, *freqs, i, numfreqs;
|
||||
int curfreq, *freqs, i, *mwatts, numfreqs;
|
||||
int ch, mode_ac, mode_battery, mode_none, acline, mode, vflag;
|
||||
uint64_t mjoules_used;
|
||||
size_t len;
|
||||
|
||||
/* Default mode for all AC states is adaptive. */
|
||||
@ -246,6 +262,7 @@ main(int argc, char * argv[])
|
||||
cpu_running_mark = DEFAULT_ACTIVE_PERCENT;
|
||||
cpu_idle_mark = DEFAULT_IDLE_PERCENT;
|
||||
poll_ival = DEFAULT_POLL_INTERVAL;
|
||||
mjoules_used = 0;
|
||||
vflag = 0;
|
||||
apm_fd = -1;
|
||||
|
||||
@ -307,7 +324,7 @@ main(int argc, char * argv[])
|
||||
/* Check if we can read the idle time and supported freqs. */
|
||||
if (read_usage_times(NULL, NULL))
|
||||
err(1, "read_usage_times");
|
||||
if (read_freqs(&numfreqs, &freqs))
|
||||
if (read_freqs(&numfreqs, &freqs, &mwatts))
|
||||
err(1, "error reading supported CPU frequencies");
|
||||
|
||||
/* Decide whether to use ACPI or APM to read the AC line status. */
|
||||
@ -316,12 +333,23 @@ main(int argc, char * argv[])
|
||||
/* Run in the background unless in verbose mode. */
|
||||
if (!vflag)
|
||||
daemon(0, 0);
|
||||
signal(SIGINT, handle_sigs);
|
||||
signal(SIGTERM, handle_sigs);
|
||||
|
||||
/* Main loop. */
|
||||
for (;;) {
|
||||
/* Check status every few milliseconds. */
|
||||
usleep(poll_ival);
|
||||
|
||||
/* If the user requested we quit, print some statistics. */
|
||||
if (exit_requested) {
|
||||
if (vflag && mjoules_used != 0)
|
||||
printf("total joules used: %u.%03u\n",
|
||||
(u_int)(mjoules_used / 1000),
|
||||
(int)mjoules_used % 1000);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Read the current AC status and record the mode. */
|
||||
acline = acline_read();
|
||||
switch (acline) {
|
||||
@ -343,6 +371,18 @@ main(int argc, char * argv[])
|
||||
if (sysctl(freq_mib, 4, &curfreq, &len, NULL, 0))
|
||||
err(1, "error reading current CPU frequency");
|
||||
|
||||
if (vflag) {
|
||||
for (i = 0; i < numfreqs; i++) {
|
||||
if (freqs[i] == curfreq)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Keep a sum of all power actually used. */
|
||||
if (i < numfreqs && mwatts[i] != -1)
|
||||
mjoules_used +=
|
||||
(mwatts[i] * (poll_ival / 1000)) / 1000;
|
||||
}
|
||||
|
||||
/* Always switch to the lowest frequency in min mode. */
|
||||
if (mode == MODE_MIN) {
|
||||
if (curfreq != freqs[numfreqs - 1]) {
|
||||
@ -409,7 +449,8 @@ main(int argc, char * argv[])
|
||||
freqs[i]);
|
||||
}
|
||||
}
|
||||
/* NOTREACHED */
|
||||
free(freqs);
|
||||
free(mwatts);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user