Index | Thread | Search

From:
Kirill A. Korinsky <kirill@korins.ky>
Subject:
Re: improvement of perfpolicy auto
To:
Vitaliy Makkoveev <mvs@openbsd.org>
Cc:
Ted Unangst <tedu@tedunangst.com>, tech@openbsd.org
Date:
Fri, 16 May 2025 02:51:54 +0200

Download raw body.

Thread
On Thu, 15 May 2025 23:25:53 +0200,
Vitaliy Makkoveev <mvs@openbsd.org> wrote:
> 
>                                                          I could say my
> gnome session works acceptable.
> 

I think that it can be improved. May I ask you to try this version and try
different hw.autoperfpolint?

My bet that 100 ms is too slow to change speed and smaller value, like 50 or
10 ms, is that should be used.


Index: sys/kern/kern_sysctl.c
===================================================================
RCS file: /home/cvs/src/sys/kern/kern_sysctl.c,v
diff -u -p -r1.468 kern_sysctl.c
--- sys/kern/kern_sysctl.c	9 May 2025 14:53:22 -0000	1.468
+++ sys/kern/kern_sysctl.c	15 May 2025 23:32:47 -0000
@@ -851,6 +851,7 @@ hw_sysctl(int *name, u_int namelen, void
 	case HW_SENSORS:
 	case HW_SETPERF:
 	case HW_PERFPOLICY:
+	case HW_PERFPOLICY_AUTO_INT:
 	case HW_BATTERY:
 #endif /* !SMALL_KERNEL */
 	case HW_ALLOWPOWERDOWN:
@@ -944,6 +945,8 @@ hw_sysctl_locked(int *name, u_int namele
 		return (sysctl_hwsetperf(oldp, oldlenp, newp, newlen));
 	case HW_PERFPOLICY:
 		return (sysctl_hwperfpolicy(oldp, oldlenp, newp, newlen));
+	case HW_PERFPOLICY_AUTO_INT:
+		return (sysctl_hwperfpolicy_auto_int(oldp, oldlenp, newp, newlen));
 #endif /* !SMALL_KERNEL */
 	case HW_ALLOWPOWERDOWN:
 		return (sysctl_securelevel_int(oldp, oldlenp, newp, newlen,
Index: sys/kern/sched_bsd.c
===================================================================
RCS file: /home/cvs/src/sys/kern/sched_bsd.c,v
diff -u -p -r1.99 sched_bsd.c
--- sys/kern/sched_bsd.c	10 Mar 2025 09:28:56 -0000	1.99
+++ sys/kern/sched_bsd.c	16 May 2025 00:39:48 -0000
@@ -575,16 +575,22 @@ current_perfpolicy(void)
 	return (hw_power) ? perfpolicy_on_ac : perfpolicy_on_battery;
 }
 
+#define PERFPOL_AUTO_HW_POWER_HIGH	80
+#define PERFPOL_AUTO_AC_POWER_HIGH	95
+
+static int perfpol_auto_interval_ms = 100;
+
 void
 setperf_auto(void *v)
 {
-	static uint64_t *idleticks, *totalticks;
-	static int downbeats;
-	int i, j = 0;
-	int speedup = 0;
+	static struct timespec last, *idletimes;
+	int i = 0;
+	int speedup = 0, load = 0, speed = 0;
+	uint64_t idle, window;
 	CPU_INFO_ITERATOR cii;
 	struct cpu_info *ci;
-	uint64_t idle, total, allidle = 0, alltotal = 0;
+	struct timespec now, ts, its;
+	struct schedstate_percpu *spc;
 
 	if (!perfpolicy_dynamic())
 		return;
@@ -597,49 +603,70 @@ setperf_auto(void *v)
 		goto faster;
 	}
 
-	if (!idleticks)
-		if (!(idleticks = mallocarray(ncpusfound, sizeof(*idleticks),
+	if (!idletimes)
+		if (!(idletimes = mallocarray(ncpusfound, sizeof(*idletimes),
 		    M_DEVBUF, M_NOWAIT | M_ZERO)))
 			return;
-	if (!totalticks)
-		if (!(totalticks = mallocarray(ncpusfound, sizeof(*totalticks),
-		    M_DEVBUF, M_NOWAIT | M_ZERO))) {
-			free(idleticks, M_DEVBUF,
-			    sizeof(*idleticks) * ncpusfound);
-			return;
-		}
+
+	nanouptime(&now);
+	timespecsub(&now, &last, &ts);
+	last = now;
+	/* window = TIMESPEC_TO_NSEC(&ts) / 1000000ULL; */
+	window = TIMESPEC_TO_NSEC(&ts);
+
 	CPU_INFO_FOREACH(cii, ci) {
 		if (!cpu_is_online(ci))
 			continue;
-		total = 0;
-		for (i = 0; i < CPUSTATES; i++) {
-			total += ci->ci_schedstate.spc_cp_time[i];
-		}
-		total -= totalticks[j];
-		idle = ci->ci_schedstate.spc_cp_time[CP_IDLE] - idleticks[j];
-		if (idle < total / 3)
-			speedup = 1;
-		alltotal += total;
-		allidle += idle;
-		idleticks[j] += idle;
-		totalticks[j] += total;
-		j++;
+
+		spc = &ci->ci_schedstate;
+
+		ts = spc->spc_runtime;
+		its = spc->spc_idleproc->p_tu.tu_runtime;
+
+		if (ci->ci_curproc == spc->spc_idleproc &&
+		    timespeccmp(&ts, &spc->spc_runtime, ==) &&
+		    timespeccmp(&now, &ts, >))
+			timespecsub(&now, &ts, &ts);
+		else
+			timespecclear(&ts);
+
+		timespecsub(&its, &idletimes[i], &its);
+		timespecadd(&idletimes[i], &its, &idletimes[i]);
+
+		timespecadd(&ts, &its, &ts);
+
+		/* idle = TIMESPEC_TO_NSEC(&ts) / 1000000ULL; */
+		idle = TIMESPEC_TO_NSEC(&ts);
+
+		if (idle <= 0)
+			speed = 100;
+
+		if (idle > window)
+			load = 0;
+		else
+			load = (100 * (window - idle)) / window;
+
+		if (load > speed)
+			speed = load;
+
+		i++;
 	}
-	if (allidle < alltotal / 2)
+
+	if (hw_power && speed >= PERFPOL_AUTO_HW_POWER_HIGH)
+		speedup = 1;
+	else if (speed >= PERFPOL_AUTO_AC_POWER_HIGH)
 		speedup = 1;
-	if (speedup && downbeats < 5)
-		downbeats++;
 
 	if (speedup && perflevel != 100) {
 faster:
 		perflevel = 100;
 		cpu_setperf(perflevel);
-	} else if (!speedup && perflevel != 0 && --downbeats <= 0) {
-		perflevel = 0;
+	} else if (!speedup && speed != perflevel) {
+		perflevel = speed;
 		cpu_setperf(perflevel);
 	}
 
-	timeout_add_msec(&setperf_to, 100);
+	timeout_add_msec(&setperf_to, perfpol_auto_interval_ms);
 }
 
 int
@@ -737,6 +764,17 @@ sysctl_hwperfpolicy(void *oldp, size_t *
 		timeout_add_msec(&setperf_to, 200);
 
 	return 0;
+}
+
+int
+sysctl_hwperfpolicy_auto_int(void *oldp, size_t *oldlenp,
+    void *newp, size_t newlen)
+{
+	if (!cpu_setperf)
+		return EOPNOTSUPP;
+
+	return sysctl_int_bounded(oldp, oldlenp, newp, newlen,
+	    &perfpol_auto_interval_ms, 1, 1000);
 }
 #endif
 
Index: sys/sys/sched.h
===================================================================
RCS file: /home/cvs/src/sys/sys/sched.h,v
diff -u -p -r1.73 sched.h
--- sys/sys/sched.h	8 Jul 2024 14:46:47 -0000	1.73
+++ sys/sys/sched.h	15 May 2025 23:33:10 -0000
@@ -174,6 +174,7 @@ void sched_barrier(struct cpu_info *ci);
 
 int sysctl_hwsetperf(void *, size_t *, void *, size_t);
 int sysctl_hwperfpolicy(void *, size_t *, void *, size_t);
+int sysctl_hwperfpolicy_auto_int(void *, size_t *, void *, size_t);
 int sysctl_hwsmt(void *, size_t *, void *, size_t);
 int sysctl_hwncpuonline(void);
 
Index: sys/sys/sysctl.h
===================================================================
RCS file: /home/cvs/src/sys/sys/sysctl.h,v
diff -u -p -r1.242 sysctl.h
--- sys/sys/sysctl.h	29 Apr 2025 02:24:32 -0000	1.242
+++ sys/sys/sysctl.h	16 May 2025 00:34:48 -0000
@@ -926,7 +926,8 @@ struct kinfo_file {
 #define	HW_POWER		26	/* int: machine has wall-power */
 #define	HW_BATTERY		27	/* node: battery */
 #define	HW_UCOMNAMES		28	/* strings: ucom names */
-#define	HW_MAXID		29	/* number of valid hw ids */
+#define	HW_PERFPOLICY_AUTO_INT	29	/* set auto perfpolicy interval */
+#define	HW_MAXID		30	/* number of valid hw ids */
 
 #define	CTL_HW_NAMES { \
 	{ 0, 0 }, \
@@ -958,6 +959,7 @@ struct kinfo_file {
 	{ "power", CTLTYPE_INT }, \
 	{ "battery", CTLTYPE_NODE }, \
 	{ "ucomnames", CTLTYPE_STRING }, \
+	{ "autoperfpolint", CTLTYPE_INT }, \
 }
 
 /*



-- 
wbr, Kirill