Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1331627 > unrolled thread
| Started by | riel@redhat.com |
|---|---|
| First post | 2016-02-11 02:10 +0100 |
| Last post | 2016-02-15 10:10 +0100 |
| Articles | 4 — 2 participants |
Back to article view | Back to linux.kernel
[PATCH 0/4 v6] sched,time: reduce nohz_full syscall overhead 40% riel@redhat.com - 2016-02-11 02:10 +0100
[PATCH 3/4] time,acct: drop irq save & restore from __acct_update_integrals riel@redhat.com - 2016-02-11 02:10 +0100
[PATCH 1/4] sched,time: remove non-power-of-two divides from __acct_update_integrals riel@redhat.com - 2016-02-11 02:20 +0100
Re: [PATCH 0/4 v6] sched,time: reduce nohz_full syscall overhead 40% Mike Galbraith <umgwanakikbuti@gmail.com> - 2016-02-15 10:10 +0100
| From | riel@redhat.com |
|---|---|
| Date | 2016-02-11 02:10 +0100 |
| Subject | [PATCH 0/4 v6] sched,time: reduce nohz_full syscall overhead 40% |
| Message-ID | <r0NVE-1Am-5@gated-at.bofh.it> |
(v6: make VIRT_CPU_ACCOUNTING_GEN jiffy granularity)
Running with nohz_full introduces a fair amount of overhead.
Specifically, various things that are usually done from the
timer interrupt are now done at syscall, irq, and guest
entry and exit times.
However, some of the code that is called every single time
has only ever worked at jiffy resolution. The code in
__acct_update_integrals was also doing some unnecessary
calculations.
Getting rid of the unnecessary calculations, without
changing any of the functionality in __acct_update_integrals
gets us about an 11% win.
Not calling the time statistics updating code more than
once per jiffy, like is done on housekeeping CPUs and on
all the CPUs of a non-nohz_full system, shaves off a
further 30%.
I tested this series with a microbenchmark calling
an invalid syscall number ten million times in a row,
on a nohz_full cpu.
Run times for the microbenchmark:
4.4 3.8 seconds
4.5-rc1 3.7 seconds
4.5-rc1 + first patch 3.3 seconds
4.5-rc1 + first 3 patches 3.1 seconds
4.5-rc1 + all patches 2.3 seconds
Same test on a non-NOHZ_FULL, non-housekeeping CPU:
all kernels 1.86 seconds
[toc] | [next] | [standalone]
| From | riel@redhat.com |
|---|---|
| Date | 2016-02-11 02:10 +0100 |
| Subject | [PATCH 3/4] time,acct: drop irq save & restore from __acct_update_integrals |
| Message-ID | <r0NVE-1Am-19@gated-at.bofh.it> |
| In reply to | #1331627 |
From: Rik van Riel <riel@redhat.com>
It looks like all the call paths that lead to __acct_update_integrals
already have irqs disabled, and __acct_update_integrals does not need
to disable irqs itself.
This is very convenient since about half the CPU time left in this
function was spent in local_irq_save alone.
Performance of a microbenchmark that calls an invalid syscall
ten million times in a row on a nohz_full CPU improves 21% vs.
4.5-rc1 with both the removal of divisions from __acct_update_integrals
and this patch, with runtime dropping from 3.7 to 2.9 seconds.
With these patches applied, the highest remaining cpu user in
the trace is native_sched_clock, which is addressed in the next
patch.
For testing purposes I stuck a WARN_ON(!irqs_disabled()) test
in __acct_update_integrals. It did not trigger.
Suggested-by: Peter Zijlstra <peterz@infradead.org>
Signed-off-by: Rik van Riel <riel@redhat.com>
---
kernel/tsacct.c | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/kernel/tsacct.c b/kernel/tsacct.c
index d12e815b7bcd..f8e26ab963ed 100644
--- a/kernel/tsacct.c
+++ b/kernel/tsacct.c
@@ -126,20 +126,18 @@ static void __acct_update_integrals(struct task_struct *tsk,
cputime_t utime, cputime_t stime)
{
cputime_t time, dtime;
- unsigned long flags;
u64 delta;
if (!likely(tsk->mm))
return;
- local_irq_save(flags);
time = stime + utime;
dtime = time - tsk->acct_timexpd;
/* Avoid division: cputime_t is often in nanoseconds already. */
delta = cputime_to_nsecs(dtime);
if (delta < TICK_NSEC)
- goto out;
+ return;
tsk->acct_timexpd = time;
/*
@@ -149,8 +147,6 @@ static void __acct_update_integrals(struct task_struct *tsk,
*/
tsk->acct_rss_mem1 += delta * get_mm_rss(tsk->mm) >> 10;
tsk->acct_vm_mem1 += delta * tsk->mm->total_vm >> 10;
-out:
- local_irq_restore(flags);
}
/**
@@ -160,9 +156,12 @@ static void __acct_update_integrals(struct task_struct *tsk,
void acct_update_integrals(struct task_struct *tsk)
{
cputime_t utime, stime;
+ unsigned long flags;
+ local_irq_save(flags);
task_cputime(tsk, &utime, &stime);
__acct_update_integrals(tsk, utime, stime);
+ local_irq_restore(flags);
}
/**
--
2.5.0
[toc] | [prev] | [next] | [standalone]
| From | riel@redhat.com |
|---|---|
| Date | 2016-02-11 02:20 +0100 |
| Subject | [PATCH 1/4] sched,time: remove non-power-of-two divides from __acct_update_integrals |
| Message-ID | <r0O5k-1E8-5@gated-at.bofh.it> |
| In reply to | #1331627 |
From: Rik van Riel <riel@redhat.com>
When running a microbenchmark calling an invalid syscall number
in a loop, on a nohz_full CPU, we spend a full 9% of our CPU
time in __acct_update_integrals.
This function converts cputime_t to jiffies, to a timeval, only to
convert the timeval back to microseconds before discarding it.
This patch leaves __acct_update_integrals functionally equivalent,
but speeds things up by about 12%, with 10 million calls to an
invalid syscall number dropping from 3.7 to 3.25 seconds.
Signed-off-by: Rik van Riel <riel@redhat.com>
---
kernel/tsacct.c | 26 ++++++++++++++++----------
1 file changed, 16 insertions(+), 10 deletions(-)
diff --git a/kernel/tsacct.c b/kernel/tsacct.c
index 975cb49e32bf..460ee2bbfef3 100644
--- a/kernel/tsacct.c
+++ b/kernel/tsacct.c
@@ -93,9 +93,11 @@ void xacct_add_tsk(struct taskstats *stats, struct task_struct *p)
{
struct mm_struct *mm;
- /* convert pages-usec to Mbyte-usec */
- stats->coremem = p->acct_rss_mem1 * PAGE_SIZE / MB;
- stats->virtmem = p->acct_vm_mem1 * PAGE_SIZE / MB;
+ /* convert pages-nsec/1024 to Mbyte-usec, see __acct_update_integrals */
+ stats->coremem = p->acct_rss_mem1 * PAGE_SIZE;
+ do_div(stats->coremem, 1000 * KB);
+ stats->virtmem = p->acct_vm_mem1 * PAGE_SIZE;
+ do_div(stats->virtmem, 1000 * KB);
mm = get_task_mm(p);
if (mm) {
/* adjust to KB unit */
@@ -125,22 +127,26 @@ static void __acct_update_integrals(struct task_struct *tsk,
{
if (likely(tsk->mm)) {
cputime_t time, dtime;
- struct timeval value;
unsigned long flags;
u64 delta;
local_irq_save(flags);
time = stime + utime;
dtime = time - tsk->acct_timexpd;
- jiffies_to_timeval(cputime_to_jiffies(dtime), &value);
- delta = value.tv_sec;
- delta = delta * USEC_PER_SEC + value.tv_usec;
+ /* Avoid division: cputime_t is often in nanoseconds already. */
+ delta = cputime_to_nsecs(dtime);
- if (delta == 0)
+ if (delta < TICK_NSEC)
goto out;
+
tsk->acct_timexpd = time;
- tsk->acct_rss_mem1 += delta * get_mm_rss(tsk->mm);
- tsk->acct_vm_mem1 += delta * tsk->mm->total_vm;
+ /*
+ * Divide by 1024 to avoid overflow, and to avoid division.
+ * The final unit reported to userspace is Mbyte-usecs,
+ * the rest of the math is done in xacct_add_tsk.
+ */
+ tsk->acct_rss_mem1 += delta * get_mm_rss(tsk->mm) >> 10;
+ tsk->acct_vm_mem1 += delta * tsk->mm->total_vm >> 10;
out:
local_irq_restore(flags);
}
--
2.5.0
[toc] | [prev] | [next] | [standalone]
| From | Mike Galbraith <umgwanakikbuti@gmail.com> |
|---|---|
| Date | 2016-02-15 10:10 +0100 |
| Message-ID | <r2nkm-7he-7@gated-at.bofh.it> |
| In reply to | #1331627 |
Hi Rik,
On Wed, 2016-02-10 at 20:08 -0500, riel@redhat.com wrote:
> I tested this series with a microbenchmark calling
> an invalid syscall number ten million times in a row,
> on a nohz_full cpu.
>
> Run times for the microbenchmark:
>
> 4.4 3.8 seconds
> 4.5-rc1 3.7 seconds
> 4.5-rc1 + first patch 3.3 seconds
> 4.5-rc1 + first 3 patches 3.1 seconds
> 4.5-rc1 + all patches 2.3 seconds
>
> Same test on a non-NOHZ_FULL, non-housekeeping CPU:
> all kernels 1.86 seconds
I tested 10M stat(".", &buf) calls, and saw a win of ~20% on a
nohz_full cpu. Below are nopreempt vs nohz_full+patches overhead
numbers from my box.
avg
4.4.1-nopreempt 0m1.652s 0m1.633s 0m1.635s 1.640 1.000
nohz_full + patches
nohz_full inactive 0m1.642s 0m1.631s 0m1.629s 1.634 .996
housekeeper CPU 0m2.013s 0m2.012s 0m2.033s 2.019 1.231
nohz_full CPU 0m2.247s 0m2.233s 0m2.239s 2.239 1.365
It still ain't free ;-) but between this set, and all the other work
that has gone in ~recently, it looks one hell of a lot better. That's
not too scary a pricetag.
-Mike
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web