mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH v2] sched/cputime: Don't account idle time twice after dyntick-idle
@ 2026-10-05 19:40 Stian Halseth
  2026-10-06 10:11 ` Frederic Weisbecker
  0 siblings, 1 reply; 6+ messages in thread
From: Stian Halseth @ 2026-10-05 19:40 UTC (permalink / raw)
  To: Frederic Weisbecker, Thomas Gleixner
  Cc: Anna-Maria Behnsen, Ingo Molnar, Peter Zijlstra, Shrikanth Hegde,
	regressions, linux-kernel

On idle exit the dyntick-idle accounting accounts the time up to now,
then the tick is restarted on its old period. The first tick accounts a
whole TICK_NSEC to whatever runs, although the part of that period
before the idle exit has just been accounted as idle time, or with
IRQ_TIME_ACCOUNTING as IRQ time. That is up to a full tick per idle
exit, and /proc/stat reports more idle time than wall time.

Record how much of the current tick period dyntick-idle has accounted,
and leave it out of the tick that ends the period.

Fixes: cf6444c3e1bb7 ("tick/sched: Unify idle cputime accounting")
Link: https://lore.kernel.org/all/20261004142724.3896396-1-stian@itx.no/
Signed-off-by: Stian Halseth <stian@itx.no>
---
v2:
- Keep the overlap per tick period, so that a second dyntick-idle
  period before the tick adds to it instead of replacing it (Frederic)
- Read it through a helper in the NO_HZ_COMMON block, with a stub in
  its #else, like kcpustat_field_dyntick(). IS_ENABLED() does not build,
  as the field only exists with NO_HZ_COMMON. The helper is static
  inline, as there is no user with VIRT_CPU_ACCOUNTING_NATIVE.

Frederic's case does not happen in my tests on its own. Since
f4c31b07b136 ("sched: idle: Consolidate the handling of two special
cases"), without a cpuidle driver or with a single state, the tick is
only stopped after it woke up the idle loop, and that tick takes the
overlap first. With a test-only change that stops the tick on every
idle entry, as a governor may, the guest added to a pending overlap
about 900 times a second under a pipe ping-pong between two CPUs.

So it is not what is left with steal time. That is the same with v2,
+0.7% to +1.4%, and only shows when the task also spins for 1 ms after
each wakeup.

Total CPU time per wall second on the loaded CPU, v2:

  SPARC T7-1, HZ=100, busiest CPU*       1.0001
  SPARC T7-1, HZ=100, 3.7 ms sleeps      1.0000
  SPARC T7-1, HZ=100, 25 ms sleeps       0.9998
  SPARC T7-1, HZ=100, pipe ping-pong     1.0000
  x86_64 KVM guest, HZ=250, 3.7 ms       0.997  (1.505 before)
  same guest, pipe ping-pong             1.000  (1.152 before)
  same guest, 9 ms sleeps                0.985

  * under its normal load, about 90 tick stops/s

The guest was tested as for v1, with and without IRQ_TIME_ACCOUNTING,
with highres=off, with steal time and with the forced restart path. The
-1.5% with 9 ms sleeps is the late tick delivery described in v1.

v1: https://lore.kernel.org/all/20261004184701.4112237-1-stian@itx.no/

 include/linux/kernel_stat.h |  7 +++++--
 kernel/sched/cputime.c      | 35 +++++++++++++++++++++++++++++------
 kernel/time/tick-sched.c    | 23 ++++++++++++++++++++---
 3 files changed, 54 insertions(+), 11 deletions(-)

diff --git a/include/linux/kernel_stat.h b/include/linux/kernel_stat.h
index 9ca6c2259dfea..6e252048b5ade 100644
--- a/include/linux/kernel_stat.h
+++ b/include/linux/kernel_stat.h
@@ -40,6 +40,9 @@ struct kernel_cpustat {
 	seqcount_t	idle_sleeptime_seq;
 	u64		idle_entrytime;
 	u64		idle_stealtime[2];
+	u64		idle_dyntick_entry;
+	u64		idle_tick_period;
+	u64		idle_tick_overlap;
 #endif
 	u64		cpustat[NR_STATS];
 };
@@ -111,7 +114,7 @@ static inline unsigned long kstat_cpu_irqs_sum(unsigned int cpu)
 #ifdef CONFIG_HAVE_VIRT_CPU_ACCOUNTING_IDLE
 
 static inline void kcpustat_dyntick_start(u64 now) { }
-static inline void kcpustat_dyntick_stop(u64 now) { }
+static inline void kcpustat_dyntick_stop(u64 now, u64 tick_start) { }
 static inline void kcpustat_irq_enter(u64 now) { }
 static inline void kcpustat_irq_exit(u64 now) { }
 static inline bool kcpustat_idle_dyntick(void) { return false; }
@@ -132,7 +135,7 @@ static inline u64 kcpustat_field_iowait(int cpu)
 #else /* !CONFIG_HAVE_VIRT_CPU_ACCOUNTING_IDLE */
 
 extern void kcpustat_dyntick_start(u64 now);
-extern void kcpustat_dyntick_stop(u64 now);
+extern void kcpustat_dyntick_stop(u64 now, u64 tick_start);
 extern void kcpustat_irq_enter(u64 now);
 extern void kcpustat_irq_exit(u64 now);
 extern u64 kcpustat_field_idle(int cpu);
diff --git a/kernel/sched/cputime.c b/kernel/sched/cputime.c
index 06bddaa738e52..3c6185e9e0963 100644
--- a/kernel/sched/cputime.c
+++ b/kernel/sched/cputime.c
@@ -381,9 +381,9 @@ void thread_group_cputime(struct task_struct *tsk, struct task_cputime *times)
  * softirq as those do not count in task exec_runtime any more.
  */
 static void irqtime_account_process_tick(struct task_struct *p, int user_tick,
-					 int ticks)
+					 u64 cputime)
 {
-	u64 other, cputime = TICK_NSEC * ticks;
+	u64 other;
 
 	/*
 	 * When returning from idle, many ticks can get accounted at
@@ -418,7 +418,7 @@ static void irqtime_account_process_tick(struct task_struct *p, int user_tick,
 
 #else /* !CONFIG_IRQ_TIME_ACCOUNTING: */
 static inline void irqtime_account_process_tick(struct task_struct *p, int user_tick,
-						int nr_ticks) { }
+						u64 cputime) { }
 #endif /* !CONFIG_IRQ_TIME_ACCOUNTING */
 
 #if defined(CONFIG_NO_HZ_COMMON) && !defined(CONFIG_HAVE_VIRT_CPU_ACCOUNTING_IDLE)
@@ -468,18 +468,34 @@ static void kcpustat_idle_start(struct kernel_cpustat *kc, u64 now)
 	write_seqcount_end(&kc->idle_sleeptime_seq);
 }
 
-void kcpustat_dyntick_stop(u64 now)
+void kcpustat_dyntick_stop(u64 now, u64 tick_start)
 {
 	struct kernel_cpustat *kc = kcpustat_this_cpu;
 
 	if (!vtime_generic_enabled_this_cpu()) {
 		WARN_ON_ONCE(!kc->idle_dyntick);
+		if (kc->idle_tick_period != tick_start) {
+			kc->idle_tick_period = tick_start;
+			kc->idle_tick_overlap = 0;
+		}
+		tick_start = max(tick_start, kc->idle_dyntick_entry);
+		if (now > tick_start)
+			kc->idle_tick_overlap += now - tick_start;
 		kcpustat_idle_stop(kc, now);
 		kc->idle_dyntick = false;
 		vtime_dyntick_stop();
 	}
 }
 
+/*
+ * The first tick after dyntick-idle covers a period that the dyntick-idle
+ * accounting may already have accounted in part.
+ */
+static inline u64 kcpustat_tick_overlap(void)
+{
+	return __this_cpu_xchg(kernel_cpustat.idle_tick_overlap, 0);
+}
+
 void kcpustat_dyntick_start(u64 now)
 {
 	struct kernel_cpustat *kc = kcpustat_this_cpu;
@@ -487,6 +503,7 @@ void kcpustat_dyntick_start(u64 now)
 	if (!vtime_generic_enabled_this_cpu()) {
 		vtime_dyntick_start();
 		kc->idle_dyntick = true;
+		kc->idle_dyntick_entry = now;
 		kcpustat_idle_start(kc, now);
 	}
 }
@@ -555,6 +572,11 @@ u64 kcpustat_field_iowait(int cpu)
 }
 EXPORT_SYMBOL_GPL(kcpustat_field_iowait);
 #else
+static inline u64 kcpustat_tick_overlap(void)
+{
+	return 0;
+}
+
 static u64 kcpustat_field_dyntick(int cpu, enum cpu_usage_stat idx,
 				  bool compute_delta, ktime_t now)
 {
@@ -695,12 +717,13 @@ void account_process_tick(struct task_struct *p, int user_tick)
 	if (kcpustat_idle_dyntick())
 		return;
 
+	cputime = TICK_NSEC - kcpustat_tick_overlap();
+
 	if (irqtime_enabled()) {
-		irqtime_account_process_tick(p, user_tick, 1);
+		irqtime_account_process_tick(p, user_tick, cputime);
 		return;
 	}
 
-	cputime = TICK_NSEC;
 	steal = steal_account_process_time(ULONG_MAX);
 
 	if (steal >= cputime)
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c
index 6c3fea3867139..1c5cefbb10812 100644
--- a/kernel/time/tick-sched.c
+++ b/kernel/time/tick-sched.c
@@ -763,13 +763,20 @@ static ktime_t tick_forward_now(ktime_t expires, ktime_t now)
 	return expires + TICK_NSEC;
 }
 
-static void tick_nohz_restart(struct tick_sched *ts, ktime_t now)
+static ktime_t tick_nohz_restart_expires(struct tick_sched *ts, ktime_t now)
 {
 	ktime_t expires = ts->last_tick;
 
 	if (now >= expires)
 		expires = tick_forward_now(expires, now);
 
+	return expires;
+}
+
+static void tick_nohz_restart(struct tick_sched *ts, ktime_t now)
+{
+	ktime_t expires = tick_nohz_restart_expires(ts, now);
+
 	if (tick_sched_flag_test(ts, TS_FLAG_HIGHRES)) {
 		hrtimer_start(&ts->sched_timer,	expires, HRTIMER_MODE_ABS_PINNED_HARD);
 	} else {
@@ -1329,6 +1336,16 @@ unsigned long tick_nohz_get_idle_calls_cpu(int cpu)
 	return ts->idle_calls;
 }
 
+static void tick_nohz_dyntick_stop(struct tick_sched *ts, ktime_t now)
+{
+	ktime_t tick_start = now;
+
+	if (!tick_nohz_full_cpu(smp_processor_id()))
+		tick_start = tick_nohz_restart_expires(ts, now) - TICK_NSEC;
+
+	kcpustat_dyntick_stop(now, tick_start);
+}
+
 void tick_nohz_idle_restart_tick(void)
 {
 	struct tick_sched *ts = this_cpu_ptr(&tick_cpu_sched);
@@ -1341,7 +1358,7 @@ void tick_nohz_idle_restart_tick(void)
 		 * no tiny amount of idle time is accounted twice.
 		 */
 		ts->idle_entrytime = ktime_get();
-		kcpustat_dyntick_stop(ts->idle_entrytime);
+		tick_nohz_dyntick_stop(ts, ts->idle_entrytime);
 		tick_nohz_restart_sched_tick(ts, ts->idle_entrytime);
 	}
 }
@@ -1385,7 +1402,7 @@ void tick_nohz_idle_exit(void)
 
 	if (tick_sched_flag_test(ts, TS_FLAG_STOPPED)) {
 		now = ktime_get();
-		kcpustat_dyntick_stop(now);
+		tick_nohz_dyntick_stop(ts, now);
 		tick_nohz_idle_update_tick(ts, now);
 	}
 
-- 
2.43.0


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v2] sched/cputime: Don't account idle time twice after dyntick-idle
  2026-10-05 19:40 [PATCH v2] sched/cputime: Don't account idle time twice after dyntick-idle Stian Halseth
@ 2026-10-06 10:11 ` Frederic Weisbecker
  2026-10-06 10:50   ` Stian Halseth
  0 siblings, 1 reply; 6+ messages in thread
From: Frederic Weisbecker @ 2026-10-06 10:11 UTC (permalink / raw)
  To: Stian Halseth
  Cc: Thomas Gleixner, Anna-Maria Behnsen, Ingo Molnar, Peter Zijlstra,
	Shrikanth Hegde, regressions, linux-kernel

Le Mon, Oct 05, 2026 at 09:40:10PM +0200, Stian Halseth a écrit :
> On idle exit the dyntick-idle accounting accounts the time up to now,
> then the tick is restarted on its old period. The first tick accounts a
> whole TICK_NSEC to whatever runs, although the part of that period
> before the idle exit has just been accounted as idle time, or with
> IRQ_TIME_ACCOUNTING as IRQ time. That is up to a full tick per idle
> exit, and /proc/stat reports more idle time than wall time.
> 
> Record how much of the current tick period dyntick-idle has accounted,
> and leave it out of the tick that ends the period.
> 
> Fixes: cf6444c3e1bb7 ("tick/sched: Unify idle cputime accounting")
> Link: https://lore.kernel.org/all/20261004142724.3896396-1-stian@itx.no/
> Signed-off-by: Stian Halseth <stian@itx.no>
> ---
> v2:
> - Keep the overlap per tick period, so that a second dyntick-idle
>   period before the tick adds to it instead of replacing it (Frederic)
> - Read it through a helper in the NO_HZ_COMMON block, with a stub in
>   its #else, like kcpustat_field_dyntick(). IS_ENABLED() does not build,
>   as the field only exists with NO_HZ_COMMON. The helper is static
>   inline, as there is no user with VIRT_CPU_ACCOUNTING_NATIVE.
> 
> Frederic's case does not happen in my tests on its own. Since
> f4c31b07b136 ("sched: idle: Consolidate the handling of two special
> cases"), without a cpuidle driver or with a single state, the tick is
> only stopped after it woke up the idle loop, and that tick takes the
> overlap first. With a test-only change that stops the tick on every
> idle entry, as a governor may, the guest added to a pending overlap
> about 900 times a second under a pipe ping-pong between two CPUs.
> 
> So it is not what is left with steal time. That is the same with v2,
> +0.7% to +1.4%, and only shows when the task also spins for 1 ms after
> each wakeup.
> 
> Total CPU time per wall second on the loaded CPU, v2:
> 
>   SPARC T7-1, HZ=100, busiest CPU*       1.0001
>   SPARC T7-1, HZ=100, 3.7 ms sleeps      1.0000
>   SPARC T7-1, HZ=100, 25 ms sleeps       0.9998
>   SPARC T7-1, HZ=100, pipe ping-pong     1.0000
>   x86_64 KVM guest, HZ=250, 3.7 ms       0.997  (1.505 before)
>   same guest, pipe ping-pong             1.000  (1.152 before)
>   same guest, 9 ms sleeps                0.985
> 
>   * under its normal load, about 90 tick stops/s
> 
> The guest was tested as for v1, with and without IRQ_TIME_ACCOUNTING,
> with highres=off, with steal time and with the forced restart path. The
> -1.5% with 9 ms sleeps is the late tick delivery described in v1.

IIUC, there is still an excess of cputime accounted here sometimes, right?
And that never happened before the patchset that rewrote the cputime idle
accounting. Am I understanding correctly?

Thanks.

-- 
Frederic Weisbecker
SUSE Labs

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v2] sched/cputime: Don't account idle time twice after dyntick-idle
  2026-10-06 10:11 ` Frederic Weisbecker
@ 2026-10-06 10:50   ` Stian Halseth
  2026-10-06 11:08     ` Frederic Weisbecker
  0 siblings, 1 reply; 6+ messages in thread
From: Stian Halseth @ 2026-10-06 10:50 UTC (permalink / raw)
  To: Frederic Weisbecker
  Cc: Thomas Gleixner, Anna-Maria Behnsen, Ingo Molnar, Peter Zijlstra,
	Shrikanth Hegde, regressions, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 3855 bytes --]


On Tue, 2026-10-06 at 12:11 +0200, Frederic Weisbecker wrote:
> Le Mon, Oct 05, 2026 at 09:40:10PM +0200, Stian Halseth a écrit :
> > On idle exit the dyntick-idle accounting accounts the time up to
> > now,
> > then the tick is restarted on its old period. The first tick
> > accounts a
> > whole TICK_NSEC to whatever runs, although the part of that period
> > before the idle exit has just been accounted as idle time, or with
> > IRQ_TIME_ACCOUNTING as IRQ time. That is up to a full tick per idle
> > exit, and /proc/stat reports more idle time than wall time.
> > 
> > Record how much of the current tick period dyntick-idle has
> > accounted,
> > and leave it out of the tick that ends the period.
> > 
> > Fixes: cf6444c3e1bb7 ("tick/sched: Unify idle cputime accounting")
> > Link:
> > https://lore.kernel.org/all/20261004142724.3896396-1-stian@itx.no/
> > Signed-off-by: Stian Halseth <stian@itx.no>
> > ---
> > v2:
> > - Keep the overlap per tick period, so that a second dyntick-idle
> >    period before the tick adds to it instead of replacing it
> > (Frederic)
> > - Read it through a helper in the NO_HZ_COMMON block, with a stub
> > in
> >    its #else, like kcpustat_field_dyntick(). IS_ENABLED() does not
> > build,
> >    as the field only exists with NO_HZ_COMMON. The helper is static
> >    inline, as there is no user with VIRT_CPU_ACCOUNTING_NATIVE.
> > 
> > Frederic's case does not happen in my tests on its own. Since
> > f4c31b07b136 ("sched: idle: Consolidate the handling of two special
> > cases"), without a cpuidle driver or with a single state, the tick
> > is
> > only stopped after it woke up the idle loop, and that tick takes
> > the
> > overlap first. With a test-only change that stops the tick on every
> > idle entry, as a governor may, the guest added to a pending overlap
> > about 900 times a second under a pipe ping-pong between two CPUs.
> > 
> > So it is not what is left with steal time. That is the same with
> > v2,
> > +0.7% to +1.4%, and only shows when the task also spins for 1 ms
> > after
> > each wakeup.
> > 
> > Total CPU time per wall second on the loaded CPU, v2:
> > 
> >    SPARC T7-1, HZ=100, busiest CPU*       1.0001
> >    SPARC T7-1, HZ=100, 3.7 ms sleeps      1.0000
> >    SPARC T7-1, HZ=100, 25 ms sleeps       0.9998|
> >    SPARC T7-1, HZ=100, pipe ping-pong     1.0000
> >    x86_64 KVM guest, HZ=250, 3.7 ms       0.997  (1.505 before)
> >    same guest, pipe ping-pong             1.000  (1.152 before)
> >    same guest, 9 ms sleeps                0.985
> > 
> >    * under its normal load, about 90 tick stops/s
> > 
> > The guest was tested as for v1, with and without
> > IRQ_TIME_ACCOUNTING,
> > with highres=off, with steal time and with the forced restart path.
> > The
> > -1.5% with 9 ms sleeps is the late tick delivery described in v1.
> 
> IIUC, there is still an excess of cputime accounted here sometimes,
> right?
> And that never happened before the patchset that rewrote the cputime
> idle
> accounting. Am I understanding correctly?
> 
> 
Only with steal time, and that is older than the rework. I ran the same
guest test on v7.1 and on ad5a9e14ec8b, the parent of cf6444c3e1bb7.
Total CPU time per wall second on the loaded vCPU:

                          v7.1    ad5a9e14ec8b   v2
  3.7 ms sleeps           0.995   0.996          0.998
  pipe ping-pong          0.997   0.996          1.000
  steal, sleep + spin     1.029   1.028          1.008
  steal, pipe ping-pong   1.338   1.341          1.001

Without steal time nothing was counted twice before the rework. With
steal time, v7.1 counted steal time during idle as both idle and steal
time. The rework fixed most of that, and what is left with a busy spin
after each wakeup is smaller than before.


/Stian

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v2] sched/cputime: Don't account idle time twice after dyntick-idle
  2026-10-06 10:50   ` Stian Halseth
@ 2026-10-06 11:08     ` Frederic Weisbecker
  2026-10-06 11:19       ` Stian Halseth
  0 siblings, 1 reply; 6+ messages in thread
From: Frederic Weisbecker @ 2026-10-06 11:08 UTC (permalink / raw)
  To: Stian Halseth
  Cc: Thomas Gleixner, Anna-Maria Behnsen, Ingo Molnar, Peter Zijlstra,
	Shrikanth Hegde, regressions, linux-kernel

Le Tue, Oct 06, 2026 at 12:50:50PM +0200, Stian Halseth a écrit :
> 
> On Tue, 2026-10-06 at 12:11 +0200, Frederic Weisbecker wrote:
> > Le Mon, Oct 05, 2026 at 09:40:10PM +0200, Stian Halseth a écrit :
> > > On idle exit the dyntick-idle accounting accounts the time up to
> > > now,
> > > then the tick is restarted on its old period. The first tick
> > > accounts a
> > > whole TICK_NSEC to whatever runs, although the part of that period
> > > before the idle exit has just been accounted as idle time, or with
> > > IRQ_TIME_ACCOUNTING as IRQ time. That is up to a full tick per idle
> > > exit, and /proc/stat reports more idle time than wall time.
> > > 
> > > Record how much of the current tick period dyntick-idle has
> > > accounted,
> > > and leave it out of the tick that ends the period.
> > > 
> > > Fixes: cf6444c3e1bb7 ("tick/sched: Unify idle cputime accounting")
> > > Link:
> > > https://lore.kernel.org/all/20261004142724.3896396-1-stian@itx.no/
> > > Signed-off-by: Stian Halseth <stian@itx.no>
> > > ---
> > > v2:
> > > - Keep the overlap per tick period, so that a second dyntick-idle
> > >    period before the tick adds to it instead of replacing it
> > > (Frederic)
> > > - Read it through a helper in the NO_HZ_COMMON block, with a stub
> > > in
> > >    its #else, like kcpustat_field_dyntick(). IS_ENABLED() does not
> > > build,
> > >    as the field only exists with NO_HZ_COMMON. The helper is static
> > >    inline, as there is no user with VIRT_CPU_ACCOUNTING_NATIVE.
> > > 
> > > Frederic's case does not happen in my tests on its own. Since
> > > f4c31b07b136 ("sched: idle: Consolidate the handling of two special
> > > cases"), without a cpuidle driver or with a single state, the tick
> > > is
> > > only stopped after it woke up the idle loop, and that tick takes
> > > the
> > > overlap first. With a test-only change that stops the tick on every
> > > idle entry, as a governor may, the guest added to a pending overlap
> > > about 900 times a second under a pipe ping-pong between two CPUs.
> > > 
> > > So it is not what is left with steal time. That is the same with
> > > v2,
> > > +0.7% to +1.4%, and only shows when the task also spins for 1 ms
> > > after
> > > each wakeup.
> > > 
> > > Total CPU time per wall second on the loaded CPU, v2:
> > > 
> > >    SPARC T7-1, HZ=100, busiest CPU*       1.0001
> > >    SPARC T7-1, HZ=100, 3.7 ms sleeps      1.0000
> > >    SPARC T7-1, HZ=100, 25 ms sleeps       0.9998|
> > >    SPARC T7-1, HZ=100, pipe ping-pong     1.0000
> > >    x86_64 KVM guest, HZ=250, 3.7 ms       0.997  (1.505 before)
> > >    same guest, pipe ping-pong             1.000  (1.152 before)
> > >    same guest, 9 ms sleeps                0.985
> > > 
> > >    * under its normal load, about 90 tick stops/s
> > > 
> > > The guest was tested as for v1, with and without
> > > IRQ_TIME_ACCOUNTING,
> > > with highres=off, with steal time and with the forced restart path.
> > > The
> > > -1.5% with 9 ms sleeps is the late tick delivery described in v1.
> > 
> > IIUC, there is still an excess of cputime accounted here sometimes,
> > right?
> > And that never happened before the patchset that rewrote the cputime
> > idle
> > accounting. Am I understanding correctly?
> > 
> > 
> Only with steal time, and that is older than the rework. I ran the same
> guest test on v7.1 and on ad5a9e14ec8b, the parent of cf6444c3e1bb7.
> Total CPU time per wall second on the loaded vCPU:
> 
>                           v7.1    ad5a9e14ec8b   v2
>   3.7 ms sleeps           0.995   0.996          0.998
>   pipe ping-pong          0.997   0.996          1.000
>   steal, sleep + spin     1.029   1.028          1.008
>   steal, pipe ping-pong   1.338   1.341          1.001
> 
> Without steal time nothing was counted twice before the rework. With
> steal time, v7.1 counted steal time during idle as both idle and steal
> time. The rework fixed most of that, and what is left with a busy spin
> after each wakeup is smaller than before.

Ok and you haven't observed a real difference between your v1 and v2, right?

Thanks.


-- 
Frederic Weisbecker
SUSE Labs

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v2] sched/cputime: Don't account idle time twice after dyntick-idle
  2026-10-06 11:08     ` Frederic Weisbecker
@ 2026-10-06 11:19       ` Stian Halseth
  2026-10-06 11:38         ` Stian Halseth
  0 siblings, 1 reply; 6+ messages in thread
From: Stian Halseth @ 2026-10-06 11:19 UTC (permalink / raw)
  To: Frederic Weisbecker
  Cc: Thomas Gleixner, Anna-Maria Behnsen, Ingo Molnar, Peter Zijlstra,
	Shrikanth Hegde, regressions, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 1186 bytes --]

On Tue, 2026-10-06 at 13:08 +0200, Frederic Weisbecker wrote:

> > Only with steal time, and that is older than the rework. I ran the
> > same
> > guest test on v7.1 and on ad5a9e14ec8b, the parent of
> > cf6444c3e1bb7.
> > Total CPU time per wall second on the loaded vCPU:
> > 
> >                           v7.1    ad5a9e14ec8b   v2
> >   3.7 ms sleeps           0.995   0.996          0.998
> >   pipe ping-pong          0.997   0.996          1.000
> >   steal, sleep + spin     1.029   1.028          1.008
> >   steal, pipe ping-pong   1.338   1.341          1.001
> > 
> > Without steal time nothing was counted twice before the rework.
> > With
> > steal time, v7.1 counted steal time during idle as both idle and
> > steal
> > time. The rework fixed most of that, and what is left with a busy
> > spin
> > after each wakeup is smaller than before.
> 
> Ok and you haven't observed a real difference between your v1 and v2,
> right?
> 
No, not in normal operation. 

It only made a difference with a test-only change that stops the tick
on every idle entry. There v2 added to a pending overlap about 900
times a second, which v1 lost.

/Stian


[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v2] sched/cputime: Don't account idle time twice after dyntick-idle
  2026-10-06 11:19       ` Stian Halseth
@ 2026-10-06 11:38         ` Stian Halseth
  0 siblings, 0 replies; 6+ messages in thread
From: Stian Halseth @ 2026-10-06 11:38 UTC (permalink / raw)
  To: Frederic Weisbecker
  Cc: Thomas Gleixner, Anna-Maria Behnsen, Ingo Molnar, Peter Zijlstra,
	Shrikanth Hegde, regressions, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 1463 bytes --]

On Tue, 2026-10-06 at 13:19 +0200, Stian Halseth wrote:
> On Tue, 2026-10-06 at 13:08 +0200, Frederic Weisbecker wrote:
> 
> > > Only with steal time, and that is older than the rework. I ran
> > > the
> > > same
> > > guest test on v7.1 and on ad5a9e14ec8b, the parent of
> > > cf6444c3e1bb7.
> > > Total CPU time per wall second on the loaded vCPU:
> > > 
> > >                           v7.1    ad5a9e14ec8b   v2
> > >   3.7 ms sleeps           0.995   0.996          0.998
> > >   pipe ping-pong          0.997   0.996          1.000
> > >   steal, sleep + spin     1.029   1.028          1.008
> > >   steal, pipe ping-pong   1.338   1.341          1.001
> > > 
> > > Without steal time nothing was counted twice before the rework.
> > > With
> > > steal time, v7.1 counted steal time during idle as both idle and
> > > steal
> > > time. The rework fixed most of that, and what is left with a busy
> > > spin
> > > after each wakeup is smaller than before.
> > 
> > Ok and you haven't observed a real difference between your v1 and
> > v2,
> > right?
> > 
> No, not in normal operation. 
> 
> It only made a difference with a test-only change that stops the tick
> on every idle entry. There v2 added to a pending overlap about 900
> times a second, which v1 lost.
> 
> /Stian
> 
IMO the pre-existing steal time issue is out of scope for this patch,
and would require a separate investigation, _if_ it's worth the time.

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2026-10-06 11:38 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-05 19:40 [PATCH v2] sched/cputime: Don't account idle time twice after dyntick-idle Stian Halseth
2026-10-06 10:11 ` Frederic Weisbecker
2026-10-06 10:50   ` Stian Halseth
2026-10-06 11:08     ` Frederic Weisbecker
2026-10-06 11:19       ` Stian Halseth
2026-10-06 11:38         ` Stian Halseth

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®