Vòng lặp nào chạy nhanh hơn
Giả sử có chương trình tên speed.c:
#include <stdio.h>
int main() {
-
int i;
-
int j;
-
int sum = 0;
-
-
for (i = 0; i < 10; ++i) {
-
sum += i;
-
}
-
-
j = 0;
-
while (j < 10) {
-
sum += j;
-
++j;
-
}
-
-
return 0;
-
}
Nếu biên dịch và chạy (trên linux)
gcc -o speed speed.c
objdump -d speed > speed.txt
Khi xem kết quả ở file speed.txt
0000000000400474 <main>:
400474: 55 push %rbp
400475: 48 89 e5 mov %rsp,%rbp
-
400478: c7 45 fc 00 00 00 00 movl $0x0,-0x4(%rbp)
-
40047f: c7 45 f4 00 00 00 00 movl $0x0,-0xc(%rbp)
-
400486: eb 0a jmp 400492 <main+0x1e>
-
400488: 8b 45 f4 mov -0xc(%rbp),%eax
-
40048b: 01 45 fc add %eax,-0x4(%rbp)
-
40048e: 83 45 f4 01 addl $0x1,-0xc(%rbp)
-
400492: 83 7d f4 09 cmpl $0x9,-0xc(%rbp)
-
400496: 7e f0 jle 400488 <main+0x14>
-
400498: c7 45 f8 00 00 00 00 movl $0x0,-0x8(%rbp)
-
40049f: eb 0a jmp 4004ab <main+0x37>
-
4004a1: 8b 45 f8 mov -0x8(%rbp),%eax
-
4004a4: 01 45 fc add %eax,-0x4(%rbp)
-
4004a7: 83 45 f8 01 addl $0x1,-0x8(%rbp)
-
4004ab: 83 7d f8 09 cmpl $0x9,-0x8(%rbp)
-
4004af: 7e f0 jle 4004a1 <main+0x2d>
-
4004b1: b8 00 00 00 00 mov $0x0,%eax
-
4004b6: c9 leaveq
-
4004b7: c3 retq
-
4004b8: 90 nop
-
4004b9: 90 nop
-
4004ba: 90 nop
-
4004bb: 90 nop
-
4004bc: 90 nop
-
4004bd: 90 nop
-
4004be: 90 nop
-
4004bf: 90 nop
Đoạn lệnh ASM của vòng lặp for
-
...
-
40047f: c7 45 f4 00 00 00 00 movl $0x0,-0xc(%rbp)
-
400486: eb 0a jmp 400492 <main+0x1e>
-
400488: 8b 45 f4 mov -0xc(%rbp),%eax
-
40048b: 01 45 fc add %eax,-0x4(%rbp)
-
40048e: 83 45 f4 01 addl $0x1,-0xc(%rbp)
-
400492: 83 7d f4 09 cmpl $0x9,-0xc(%rbp)
-
400496: 7e f0 jle 400488 <main+0x14>
-
...
Đoạn lệnh ASM của vòng lặp while
-
...
-
400498: c7 45 f8 00 00 00 00 movl $0x0,-0x8(%rbp)
-
40049f: eb 0a jmp 4004ab <main+0x37>
-
4004a1: 8b 45 f8 mov -0x8(%rbp),%eax
-
4004a4: 01 45 fc add %eax,-0x4(%rbp)
-
4004a7: 83 45 f8 01 addl $0x1,-0x8(%rbp)
-
4004ab: 83 7d f8 09 cmpl $0x9,-0x8(%rbp)
-
4004af: 7e f0 jle 4004a1 <main+0x2d>
-
...
Nhận thấy rằng hai mã lệnh ASM của hai vòng lặp là giống nhau, nên chúng cùng hiệu năng.
-
0000000000400474 <main>:
-
400474: 55 push %rbp
-
400475: 48 89 e5 mov %rsp,%rbp
-
400478: c7 45 fc 00 00 00 00 movl $0x0,-0x4(%rbp)
-
40047f: c7 45 f4 00 00 00 00 movl $0x0,-0xc(%rbp)
-
400486: eb 0a jmp 400492 <main+0x1e>
-
400488: 8b 45 f4 mov -0xc(%rbp),%eax
-
40048b: 01 45 fc add %eax,-0x4(%rbp)
-
40048e: 83 45 f4 01 addl $0x1,-0xc(%rbp)
-
400492: 83 7d f4 09 cmpl $0x9,-0xc(%rbp)
-
400496: 7e f0 jle 400488 <main+0x14>
-
400498: c7 45 f8 00 00 00 00 movl $0x0,-0x8(%rbp)
-
40049f: eb 0a jmp 4004ab <main+0x37>
-
4004a1: 8b 45 f8 mov -0x8(%rbp),%eax
-
4004a4: 01 45 fc add %eax,-0x4(%rbp)
-
4004a7: 83 45 f8 01 addl $0x1,-0x8(%rbp)
-
4004ab: 83 7d f8 09 cmpl $0x9,-0x8(%rbp)
-
4004af: 7e f0 jle 4004a1 <main+0x2d>
-
4004b1: b8 00 00 00 00 mov $0x0,%eax
-
4004b6: c9 leaveq
-
4004b7: c3 retq
-
4004b8: 90 nop
-
4004b9: 90 nop
-
4004ba: 90 nop
-
4004bb: 90 nop
-
4004bc: 90 nop
-
4004bd: 90 nop
-
4004be: 90 nop
-
4004bf: 90 nop
The first loop (the for
loop) uses the following code:
-
...
-
40047f: c7 45 f4 00 00 00 00 movl $0x0,-0xc(%rbp)
-
400486: eb 0a jmp 400492 <main+0x1e>
-
400488: 8b 45 f4 mov -0xc(%rbp),%eax
-
40048b: 01 45 fc add %eax,-0x4(%rbp)
-
40048e: 83 45 f4 01 addl $0x1,-0xc(%rbp)
-
400492: 83 7d f4 09 cmpl $0x9,-0xc(%rbp)
-
400496: 7e f0 jle 400488 <main+0x14>
-
...
The second loop (the while
loop) uses the following code:
-
...
-
400498: c7 45 f8 00 00 00 00 movl $0x0,-0x8(%rbp)
-
40049f: eb 0a jmp 4004ab <main+0x37>
-
4004a1: 8b 45 f8 mov -0x8(%rbp),%eax
-
4004a4: 01 45 fc add %eax,-0x4(%rbp)
-
4004a7: 83 45 f8 01 addl $0x1,-0x8(%rbp)
-
4004ab: 83 7d f8 09 cmpl $0x9,-0x8(%rbp)
-
4004af: 7e f0 jle 4004a1 <main+0x2d>
-
...