Commit 3c829c367a1a52550378584a657768217971e587
Committed by
 Linus Torvalds
1 parent
953a7f2066
Exists in
master
and in
4 other branches
[PATCH] Reducing local_bh_enable/disable overhead in irqtrace
The recent changes from irqtrace feature has added overheads to local_bh_disable and local_bh_enable that reduces UDP performance across x86_64 and IA64, even though IA64 does not support the irqtrace feature. Patch in question is [PATCH]lockdep: irqtrace subsystem, core http://www.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=c ommit;h=de30a2b355ea85350ca2f58f3b9bf4e5bc007986 Prior to this patch, local_bh_disable was a short macro. Now it is a function which calls __local_bh_disable with added irq flags save and restore. The irq flags save and restore were also added to local_bh_enable, probably for injecting the trace irqs code. This overhead is on the generic code path across all architectures. On a IA_64 test machine (Itanium-2 1.6 GHz) running a benchmark like netperf's UDP streaming test, the added overhead results in a drop of 3% in throughput, as udp_sendmsg calls the local_bh_enable/disable several times. Other workloads that have heavy usages of local_bh_enable/disable could also be affected. The patch ideally should not have affected IA-64 performance as it does not have IRQ tracing support. A significant portion of the overhead is in the added irq flags save and restore, which I think is not needed if IRQ tracing is unused. A suggested patch is attached below that recovers the lost performance. However, the "ifdef"s in the patch are a bit ugly. Signed-off-by: Tim Chen <tim.c.chen@intel.com> Acked-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Showing 1 changed file with 18 additions and 0 deletions Side-by-side Diff
kernel/softirq.c
| ... | ... | @@ -65,6 +65,7 @@ | 
| 65 | 65 | * This one is for softirq.c-internal use, | 
| 66 | 66 | * where hardirqs are disabled legitimately: | 
| 67 | 67 | */ | 
| 68 | +#ifdef CONFIG_TRACE_IRQFLAGS | |
| 68 | 69 | static void __local_bh_disable(unsigned long ip) | 
| 69 | 70 | { | 
| 70 | 71 | unsigned long flags; | 
| ... | ... | @@ -80,6 +81,13 @@ | 
| 80 | 81 | trace_softirqs_off(ip); | 
| 81 | 82 | raw_local_irq_restore(flags); | 
| 82 | 83 | } | 
| 84 | +#else /* !CONFIG_TRACE_IRQFLAGS */ | |
| 85 | +static inline void __local_bh_disable(unsigned long ip) | |
| 86 | +{ | |
| 87 | + add_preempt_count(SOFTIRQ_OFFSET); | |
| 88 | + barrier(); | |
| 89 | +} | |
| 90 | +#endif /* CONFIG_TRACE_IRQFLAGS */ | |
| 83 | 91 | |
| 84 | 92 | void local_bh_disable(void) | 
| 85 | 93 | { | 
| 86 | 94 | |
| 87 | 95 | |
| 88 | 96 | |
| ... | ... | @@ -121,12 +129,16 @@ | 
| 121 | 129 | |
| 122 | 130 | void local_bh_enable(void) | 
| 123 | 131 | { | 
| 132 | +#ifdef CONFIG_TRACE_IRQFLAGS | |
| 124 | 133 | unsigned long flags; | 
| 125 | 134 | |
| 126 | 135 | WARN_ON_ONCE(in_irq()); | 
| 136 | +#endif | |
| 127 | 137 | WARN_ON_ONCE(irqs_disabled()); | 
| 128 | 138 | |
| 139 | +#ifdef CONFIG_TRACE_IRQFLAGS | |
| 129 | 140 | local_irq_save(flags); | 
| 141 | +#endif | |
| 130 | 142 | /* | 
| 131 | 143 | * Are softirqs going to be turned on now: | 
| 132 | 144 | */ | 
| 133 | 145 | |
| 134 | 146 | |
| 135 | 147 | |
| ... | ... | @@ -142,18 +154,22 @@ | 
| 142 | 154 | do_softirq(); | 
| 143 | 155 | |
| 144 | 156 | dec_preempt_count(); | 
| 157 | +#ifdef CONFIG_TRACE_IRQFLAGS | |
| 145 | 158 | local_irq_restore(flags); | 
| 159 | +#endif | |
| 146 | 160 | preempt_check_resched(); | 
| 147 | 161 | } | 
| 148 | 162 | EXPORT_SYMBOL(local_bh_enable); | 
| 149 | 163 | |
| 150 | 164 | void local_bh_enable_ip(unsigned long ip) | 
| 151 | 165 | { | 
| 166 | +#ifdef CONFIG_TRACE_IRQFLAGS | |
| 152 | 167 | unsigned long flags; | 
| 153 | 168 | |
| 154 | 169 | WARN_ON_ONCE(in_irq()); | 
| 155 | 170 | |
| 156 | 171 | local_irq_save(flags); | 
| 172 | +#endif | |
| 157 | 173 | /* | 
| 158 | 174 | * Are softirqs going to be turned on now: | 
| 159 | 175 | */ | 
| 160 | 176 | |
| ... | ... | @@ -169,7 +185,9 @@ | 
| 169 | 185 | do_softirq(); | 
| 170 | 186 | |
| 171 | 187 | dec_preempt_count(); | 
| 188 | +#ifdef CONFIG_TRACE_IRQFLAGS | |
| 172 | 189 | local_irq_restore(flags); | 
| 190 | +#endif | |
| 173 | 191 | preempt_check_resched(); | 
| 174 | 192 | } | 
| 175 | 193 | EXPORT_SYMBOL(local_bh_enable_ip); |