diff options
author | Eric Dumazet <edumazet@google.com> | 2013-01-10 18:26:34 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-01-10 18:33:01 -0500 |
commit | c10d73671ad30f54692f7f69f0e09e75d3a8926a (patch) | |
tree | ef875858caef802617a3f54183a344361c0151b7 /kernel/softirq.c | |
parent | 1def9238d4aa2146924994aa4b7dc861f03b9362 (diff) |
softirq: reduce latencies
In various network workloads, __do_softirq() latencies can be up
to 20 ms if HZ=1000, and 200 ms if HZ=100.
This is because we iterate 10 times in the softirq dispatcher,
and some actions can consume a lot of cycles.
This patch changes the fallback to ksoftirqd condition to :
- A time limit of 2 ms.
- need_resched() being set on current task
When one of this condition is met, we wakeup ksoftirqd for further
softirq processing if we still have pending softirqs.
Using need_resched() as the only condition can trigger RCU stalls,
as we can keep BH disabled for too long.
I ran several benchmarks and got no significant difference in
throughput, but a very significant reduction of latencies (one order
of magnitude) :
In following bench, 200 antagonist "netperf -t TCP_RR" are started in
background, using all available cpus.
Then we start one "netperf -t TCP_RR", bound to the cpu handling the NIC
IRQ (hard+soft)
Before patch :
# netperf -H 7.7.7.84 -t TCP_RR -T2,2 -- -k
RT_LATENCY,MIN_LATENCY,MAX_LATENCY,P50_LATENCY,P90_LATENCY,P99_LATENCY,MEAN_LATENCY,STDDEV_LATENCY
MIGRATED TCP REQUEST/RESPONSE TEST from 0.0.0.0 (0.0.0.0) port 0 AF_INET
to 7.7.7.84 () port 0 AF_INET : first burst 0 : cpu bind
RT_LATENCY=550110.424
MIN_LATENCY=146858
MAX_LATENCY=997109
P50_LATENCY=305000
P90_LATENCY=550000
P99_LATENCY=710000
MEAN_LATENCY=376989.12
STDDEV_LATENCY=184046.92
After patch :
# netperf -H 7.7.7.84 -t TCP_RR -T2,2 -- -k
RT_LATENCY,MIN_LATENCY,MAX_LATENCY,P50_LATENCY,P90_LATENCY,P99_LATENCY,MEAN_LATENCY,STDDEV_LATENCY
MIGRATED TCP REQUEST/RESPONSE TEST from 0.0.0.0 (0.0.0.0) port 0 AF_INET
to 7.7.7.84 () port 0 AF_INET : first burst 0 : cpu bind
RT_LATENCY=40545.492
MIN_LATENCY=9834
MAX_LATENCY=78366
P50_LATENCY=33583
P90_LATENCY=59000
P99_LATENCY=69000
MEAN_LATENCY=38364.67
STDDEV_LATENCY=12865.26
Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: David Miller <davem@davemloft.net>
Cc: Tom Herbert <therbert@google.com>
Cc: Ben Hutchings <bhutchings@solarflare.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'kernel/softirq.c')
-rw-r--r-- | kernel/softirq.c | 17 |
1 files changed, 9 insertions, 8 deletions
diff --git a/kernel/softirq.c b/kernel/softirq.c index ed567babe789..47cb991c6ba4 100644 --- a/kernel/softirq.c +++ b/kernel/softirq.c | |||
@@ -195,21 +195,21 @@ void local_bh_enable_ip(unsigned long ip) | |||
195 | EXPORT_SYMBOL(local_bh_enable_ip); | 195 | EXPORT_SYMBOL(local_bh_enable_ip); |
196 | 196 | ||
197 | /* | 197 | /* |
198 | * We restart softirq processing MAX_SOFTIRQ_RESTART times, | 198 | * We restart softirq processing for at most 2 ms, |
199 | * and we fall back to softirqd after that. | 199 | * and if need_resched() is not set. |
200 | * | 200 | * |
201 | * This number has been established via experimentation. | 201 | * These limits have been established via experimentation. |
202 | * The two things to balance is latency against fairness - | 202 | * The two things to balance is latency against fairness - |
203 | * we want to handle softirqs as soon as possible, but they | 203 | * we want to handle softirqs as soon as possible, but they |
204 | * should not be able to lock up the box. | 204 | * should not be able to lock up the box. |
205 | */ | 205 | */ |
206 | #define MAX_SOFTIRQ_RESTART 10 | 206 | #define MAX_SOFTIRQ_TIME msecs_to_jiffies(2) |
207 | 207 | ||
208 | asmlinkage void __do_softirq(void) | 208 | asmlinkage void __do_softirq(void) |
209 | { | 209 | { |
210 | struct softirq_action *h; | 210 | struct softirq_action *h; |
211 | __u32 pending; | 211 | __u32 pending; |
212 | int max_restart = MAX_SOFTIRQ_RESTART; | 212 | unsigned long end = jiffies + MAX_SOFTIRQ_TIME; |
213 | int cpu; | 213 | int cpu; |
214 | unsigned long old_flags = current->flags; | 214 | unsigned long old_flags = current->flags; |
215 | 215 | ||
@@ -264,11 +264,12 @@ restart: | |||
264 | local_irq_disable(); | 264 | local_irq_disable(); |
265 | 265 | ||
266 | pending = local_softirq_pending(); | 266 | pending = local_softirq_pending(); |
267 | if (pending && --max_restart) | 267 | if (pending) { |
268 | goto restart; | 268 | if (time_before(jiffies, end) && !need_resched()) |
269 | goto restart; | ||
269 | 270 | ||
270 | if (pending) | ||
271 | wakeup_softirqd(); | 271 | wakeup_softirqd(); |
272 | } | ||
272 | 273 | ||
273 | lockdep_softirq_exit(); | 274 | lockdep_softirq_exit(); |
274 | 275 | ||