syscall latency improvement #1
A message that is not in the archive (sent off-list or not yet received): 18993.1011984842@warthog.cambridge.redhat.com.suse.lists.linux.kernel
Quoted 3 lines · Linus Torvalds
Looking at the code, I suspect that 99.9% of this "improvement" comes from one thing, and one thing only: you removed the "cli" in the system call return path.
It doesn't explain the Athlon speedups. On athlon cli is ~4 cycles.
-Andi
Quoted 2 lines · Andi Kleen
It doesn't explain the Athlon speedups. On athlon cli is ~4 cycles.
.. and it probably serializes the instruction stream.
Look at the patch.
The _only_ thing it does for the system call path is:
- remove the "cli"
- change
cmpl $0,.. jne cmp $0,.. jne
into
movl ..,reg testl reg,reg jne
and the latter may be worth a cycle (or two, if the CPU happens to like the second form better for some other reason), but it's certainly not noticeable.
A 3.4% improvement is equivalent to something like 9 cycles, so the "cli" being faster on Athlon than on a PIII certainly explains why it's less noticeable on the Athlon, but it still makes me suspect that the _real_ cost of the cli is on the order of 8 cycles.
It should be eminently testable. Just remove the cli from the standard kernel, and do before-and-after tests.
Linus
Quoted 6 lines · Linus Torvalds
Quoted 2 lines · Andi Kleen
It doesn't explain the Athlon speedups. On athlon cli is ~4 cycles.
.. and it probably serializes the instruction stream.
I have word from AMD engineering that it doesn't stall the pipeline or serializes.
(I asked the question during the design of the x86-64 syscall code)
-Andi
Quoted 10 lines · Andi Kleen
Quoted 6 lines · Linus Torvalds
Quoted 2 lines · Andi Kleen
It doesn't explain the Athlon speedups. On athlon cli is ~4 cycles.
.. and it probably serializes the instruction stream.
I have word from AMD engineering that it doesn't stall the pipeline or serializes.
Note that it may not be the "cli" itself - the "iret" may be slower if it has to enable interrupts that were disabled before. Ie the iret microcode may have the equivalent of
/* Did eflags change? */
if ((new_eflags ^ old_eflags) & IF_MASK)
.. do sti/cli as appropriate ..
which would mean that the "cli" itself may take 4 cycles, but the "sti" implicit in the iret will _also_ take 4 cycles and is optimized away when not needed.
Which would add up to the 8 cycles needed for a ~3.4% speedup (this is assuming the baseline is something like 250 cycles per system call, I've not checked that assumption).
Linus
Quoted 21 lines · Linus Torvalds
Quoted 10 lines · Andi Kleen
Quoted 6 lines · Linus Torvalds
Quoted 2 lines · Andi Kleen
It doesn't explain the Athlon speedups. On athlon cli is ~4 cycles.
.. and it probably serializes the instruction stream.
I have word from AMD engineering that it doesn't stall the pipeline or serializes.
Note that it may not be the "cli" itself - the "iret" may be slower if it has to enable interrupts that were disabled before. Ie the iret microcode may have the equivalent of
/* Did eflags change? */
if ((new_eflags^old_eflags) &IF_MASK)
.. do sti/cli as appropriate ..
Quoted 7 lines
which would mean that the "cli" itself may take 4 cycles, but the "sti" implicit in the iret will _also_ take 4 cycles and is optimized away when not needed.
Which would add up to the 8 cycles needed for a ~3.4% speedup (this is assuming the baseline is something like 250 cycles per system call, I've not checked that assumption).
guys, why don't you use #rdtsc to discover where perf improvement comes from ?
- Davide
Quoted 8 lines · Linus Torvalds
Quoted 6 lines · Andi Kleen
Quoted 5 lines · Linus Torvalds
Quoted 2 lines · Andi Kleen
It doesn't explain the Athlon speedups. On athlon cli is ~4 cycles.
Quoted 8 lines
Quoted 4 lines
Quoted 1 line
.. and it probably serializes the instruction stream.
I have word from AMD engineering that it doesn't stall the pipeline or serializes.
Note that it may not be the "cli" itself - the "iret" may be slower if it has to enable interrupts that were disabled before. Ie the iret microcode may have the equivalent of
[...]
Yes that could explain it. I ignored it on x86-64 because it always uses SYSCALL/SYSRET (at least for 64bit) @)
The real fix for that would be support of SYSENTER/SYSCALL on 32bit too (more likely SYSENTER because it's supported by Athlons and SYSCALL is too broken on K6 to be usable)
An int $0x80 does a awful lot of locked cycles for example and IRET is also not exactly a speed daemon and very complex.
SYSENTER/SYSEXIT would be likely a much bigger win than nanooptimizations of a few cycles around this.
-Andi
Quoted 3 lines · Andi Kleen
The real fix for that would be support of SYSENTER/SYSCALL on 32bit too (more likely SYSENTER because it's supported by Athlons and SYSCALL is too broken on K6 to be usable)
There's an implementation at http://fy.chalmers.se/~appro/linux/sysenter.c
Haven't looked at it long enough to see how good/bad it is..
Signature · 2 lines
| Dave Jones. http://www.codemonkey.org.uk | SuSE Labs
Quoted 4 lines · Linus Torvalds
It should be eminently testable. Just remove the cli from the standard kernel, and do before-and-after tests.
#include <unistd.h>
main()
{
int i = 100 * 1000 * 1000;
while (i--)
getpid();
}With cli:
./a.out 22.05s user 15.31s system 99% cpu 37.361 total
without cli:
./a.out 18.29s user 17.42s system 99% cpu 35.731 total
That's 4.6%. Intel P3.
It's also 306 cycles per iteration. So the cli added 14 cycles.
-
Quoted 8 lines · Andrew Morton
With cli:
./a.out 22.05s user 15.31s system 99% cpu 37.361 totalwithout cli:
./a.out 18.29s user 17.42s system 99% cpu 35.731 totalThat's 4.6%. Intel P3.
Same program, AMD Athlon MP 1600 (booted UP), kernel 2.5.3-pre5.
with cli: real 0m19.706s user 0m11.400s sys 0m8.290s
without cli: real 0m19.449s user 0m10.630s sys 0m8.820s
That is 1.3% improvement.
Robert Love
Quoted 6 lines · Robert Love
Same program, AMD Athlon MP 1600 (booted UP), kernel 2.5.3-pre5.
with cli: real 0m19.706s user 0m11.400s sys 0m8.290s
without cli: real 0m19.449s user 0m10.630s sys 0m8.820sThat is 1.3% improvement.
And let me add with David Howell's patch:
patch: real 0m19.305s user 0m8.130s sys 0m11.180s
Which is 0.7% faster than without cli, and 2.07% faster than the stock (with cli) kernel. This is the average of three runs, btw.
Robert Love