📜 ⬆️ ⬇️

What is faster while (true) or for (;;)?

In the raws of different authors, I saw different versions of the eternal cycle. Most often I met the following:
while (true) { ... } 

and
 for (;;) { ... } 

Since everyone defended “his own eternal cycle” as his own, I decided to find out. Who writes more optimal code.

I wrote 2 sources:

while.c:
 #include <stdio.h> int main (int argc, char* argv[]) { while(1){ printf("1\n"); } } 


for.c:
 #include <stdio.h> int main (int argc, char* argv[]) { for(;;){ printf("1\n"); } } 

')
I collected them:
 $ gcc -O3 while.c -o while.o3 $ gcc -O2 while.c -o while.o2 $ gcc -O1 while.c -o while.o1 $ gcc -O3 for.c -o for.o3 $ gcc -O2 for.c -o for.o2 $ gcc -O1 for.c -o for.o1 


And disassembled. If you are too lazy to read assembler lists, you can scroll down the page. Actually listings:
 $ objdump -d ./while.o3 ... 0000000000400430 <main>: 400430: 48 83 ec 08 sub $0x8,%rsp 400434: 0f 1f 40 00 nopl 0x0(%rax) 400438: bf d4 05 40 00 mov $0x4005d4,%edi 40043d: e8 be ff ff ff callq 400400 <puts@plt> 400442: eb f4 jmp 400438 <main+0x8> ... $ objdump -d ./while.o2 ... 0000000000400430 <main>: 400430: 48 83 ec 08 sub $0x8,%rsp 400434: 0f 1f 40 00 nopl 0x0(%rax) 400438: bf d4 05 40 00 mov $0x4005d4,%edi 40043d: e8 be ff ff ff callq 400400 <puts@plt> 400442: eb f4 jmp 400438 <main+0x8> ... $ objdump -d ./while.o1 ... 000000000040051c <main>: 40051c: 48 83 ec 08 sub $0x8,%rsp 400520: bf d4 05 40 00 mov $0x4005d4,%edi 400525: e8 d6 fe ff ff callq 400400 <puts@plt> 40052a: eb f4 jmp 400520 <main+0x4> ... $ objdump -d ./for.o1 ... 000000000040051c <main>: 40051c: 48 83 ec 08 sub $0x8,%rsp 400520: bf d4 05 40 00 mov $0x4005d4,%edi 400525: e8 d6 fe ff ff callq 400400 <puts@plt> 40052a: eb f4 jmp 400520 <main+0x4> ... $ objdump -d ./for.o2 ... 0000000000400430 <main>: 400430: 48 83 ec 08 sub $0x8,%rsp 400434: 0f 1f 40 00 nopl 0x0(%rax) 400438: bf d4 05 40 00 mov $0x4005d4,%edi 40043d: e8 be ff ff ff callq 400400 <puts@plt> 400442: eb f4 jmp 400438 <main+0x8> ... $ objdump -d ./for.o3 0000000000400430 <main>: 400430: 48 83 ec 08 sub $0x8,%rsp 400434: 0f 1f 40 00 nopl 0x0(%rax) 400438: bf d4 05 40 00 mov $0x4005d4,%edi 40043d: e8 be ff ff ff callq 400400 <puts@plt> 400442: eb f4 jmp 400438 <main+0x8> 


Parsing on the fingers



Various optimizations did not affect the implementation of the while (true) loop - it always executed 3 commands: mov, callq and jmp. The same optimization did not affect the implementation of for - it was also always from 3 commands: mov, callq, jmp. Between themselves mov, callq and jmp were no different. The length of commands in bytes is unchanged in all 6 cases.

There is only a small difference between the implementations of -O1 and -O2 / -O3 jmp running on main + 4 and not on main + 8, but given that this is a static address (as you can see from the asm code), it also does not carry the difference performance ... Although ... and suddenly the memory pages are different, because as far as I know for the gestures between different memory pages in x86 (and amd64), additional efforts are required!

We learn:
400438/4096 = 97,763183594
400520/4096 = 97,783203125

It has passed. One memory page. Yes, this is page 97 of the virtual memory of the process's virtual address space. But it is precisely what we need.

Total


while (true) and for (;;) are identical in performance between themselves and with any optimizations of -Ox. So if you are asked which of them is faster - feel free to say that “for (;;)” - 8 characters to write faster than “while (true)” - 12 characters.

For those who do not believe that without -Ox will be the same:
 $ gcc while.c -o while.noO $ objdump -d while.noO ... 40052b: bf e4 05 40 00 mov $0x4005e4,%edi 400530: e8 cb fe ff ff callq 400400 <puts@plt> 400535: eb f4 jmp 40052b <main+0xf> ... $ gcc for.c -o for.noO $ objdump -d for.noO ... 40052b: bf e4 05 40 00 mov $0x4005e4,%edi 400530: e8 cb fe ff ff callq 400400 <puts@plt> 400535: eb f4 jmp 40052b <main+0xf> ... 


PS Of course all this will be true on the compiler “gcc version 4.7.2 (Debian 4.7.2-5)”

Source: https://habr.com/ru/post/198588/


All Articles