В сырых произведениях разных авторов я видел разные версии вечного цикла.
Чаще всего мне попадалось следующее:
Иwhile (true) { .
}
for (;;) {
.
}
Поскольку каждый защищал «свой вечный цикл» как свой, я решил разобраться в нем.
Кто пишет более оптимальный код? Я написал 2 источника: пока.
с: #include <stdio.h>
int main (int argc, char* argv[])
{
while(1){
printf("1\n");
}
}
для.
c: #include <stdio.h>
int main (int argc, char* argv[])
{
for(;;){
printf("1\n");
}
}
Собрал их: $ 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
И разобрал его.
Если вам лень читать книги сборочных списков, вы можете прокрутить страницу вниз.
Собственно списки:
$ 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>
Давайте разберемся на пальцах
Различные оптимизации не повлияли на реализацию цикла while (true) — он всегда выполнял 3 команды: mov, callq и jmp. Также оптимизации не затронули реализацию for — она тоже всегда состояла из 3-х команд: mov, callq, jmp. mov, callq и jmp ничем не отличались друг от друга.Длина команд в байтах не меняется во всех 6 случаях.
Между реализациями есть лишь небольшая разница -O1 и -O2/-O3 jmp выполнялся на main+4, а не на main+8, но учитывая, что это статический адрес (как видно из ассемблерного кода), он тоже не влияет на производительность.
Хотя.
а вдруг страницы памяти разные, ведь насколько я знаю, перемещения между разными страницами памяти в x86 (и amd64) требуют дополнительных усилий со стороны процессора! Давай выясним: 400438/4096 = 97,763183594 400520/4096 = 97,783203125 Оно пролетело мимо.
Страница памяти только одна.
Да, это страница 97 виртуальной памяти виртуального адресного пространства процесса.
Но это именно то, что нам нужно.
Нижняя граница
while (true) и for (;;) идентичны по производительности друг другу и любым оптимизациям -Ox. Так что если вас спросят, какой из них быстрее, смело отвечайте, что «for (;;)» — 8 символов писать быстрее, чем « while (true)» — 12 символов.
Для тех, кто не верит, что без -Ox будет то же самое: $ 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> .
P.S. Разумеется, все это будет справедливо для компилятора «gcc версии 4.7.2 (Debian 4.7.2-5)».
Теги: #C++ #C++ # while #for #GCC #Assembler #objdump #C++ #C++
-
Шампольон, Жан-Франсуа
19 Oct, 24 -
Оптимизация Пути Зарубежного Патентования
19 Oct, 24 -
Putty В Linux: Как Скопировать Текст
19 Oct, 24 -
Уапортал Сменил Владельца
19 Oct, 24