Page 1 of 1

while(1), for(;;) and twiddling of thumbs

Posted: Mon Aug 12, 2013 11:09 pm
by phillid
I've always used while(1) in C for an infinite loop, and overlooked for(;;) because it makes less sense and degrades readability somewhat. I decided to investigate whether one has any advantage over the other once the code is compiled:

for(;;){}

Code: Select all

080483d0 <main>:
 80483d0:	55                   	push   %ebp
 80483d1:	89 e5                	mov    %esp,%ebp
 80483d3:	eb fe                	jmp    80483d3 <main+0x3>
 80483d5:	66 90                	xchg   %ax,%ax
 80483d7:	66 90                	xchg   %ax,%ax
 80483d9:	66 90                	xchg   %ax,%ax
 80483db:	66 90                	xchg   %ax,%ax
 80483dd:	66 90                	xchg   %ax,%ax
 80483df:	90                   	nop

while(1){}

Code: Select all

080483d0 <main>:
 80483d0:	55                   	push   %ebp
 80483d1:	89 e5                	mov    %esp,%ebp
 80483d3:	eb fe                	jmp    80483d3 <main+0x3>
 80483d5:	66 90                	xchg   %ax,%ax
 80483d7:	66 90                	xchg   %ax,%ax
 80483d9:	66 90                	xchg   %ax,%ax
 80483db:	66 90                	xchg   %ax,%ax
 80483dd:	66 90                	xchg   %ax,%ax
 80483df:	90                   	nop
So it's all fine and dandy - they both result in an empty, infinite loop. Cool.

What I was intrigued about was the useless xchg instructions, and the nop. Why would the compiler put these in here and leave the computer twiddling its thumbs? The only things I can think of is to pad the section for some reason... I can see the pattern of 906690669066 in there.. is that something significant? I'd better pull the ASCII chart out.

Any thoughts?

Re: while(1), for(;;) and twiddling of thumbs

Posted: Mon Aug 12, 2013 11:41 pm
by Combuster
What I was intrigued about was the useless xchg instructions, and the nop.
It aligns the start of the next function to the start of a cache line.

Re: while(1), for(;;) and twiddling of thumbs

Posted: Mon Aug 12, 2013 11:43 pm
by bluemoon
They are for padding. Those values are chosen because it looks more friendly for instruction prefetch and decoders compares to random garbages.

Re: while(1), for(;;) and twiddling of thumbs

Posted: Tue Aug 13, 2013 1:07 am
by phillid
Thanks for that - just as I thought, it was padding. But for prefetch. I'm not so hot on subjects like prefetch so bear with me when I ask: Why do I not have to worry about prefetch when I'm writing directly in Assembler? Is it something I should do but don't have to?

Cheers

Re: while(1), for(;;) and twiddling of thumbs

Posted: Tue Aug 13, 2013 1:15 am
by dozniak
You always care about prefetch if you want to run fast.

Re: while(1), for(;;) and twiddling of thumbs

Posted: Tue Aug 13, 2013 1:22 am
by Kevin
phillid wrote:Why do I not have to worry about prefetch when I'm writing directly in Assembler? Is it something I should do but don't have to?
It is one of the reasons why hand-written assembly may well perform worse than C code compiled by those stupid C compilers. Especially true for the code of those who say they write everything in assembly for the sake of performance.

Re: while(1), for(;;) and twiddling of thumbs

Posted: Tue Aug 13, 2013 1:28 am
by Combuster
phillid wrote:Is it something I should do but don't have to?
The first goal of code is that it should work :wink: - then you can make it faster and more efficient, and at some point you'll be spending more time at trying to find a better solution than you're ever going to get back.

If you want fast code, you'd be best off to let the compiler do the micro-optimisations for you.

Re: while(1), for(;;) and twiddling of thumbs

Posted: Tue Aug 13, 2013 1:41 am
by phillid
Right, fair enough, makes sense. Thanks all! :)

Re: while(1), for(;;) and twiddling of thumbs

Posted: Fri Aug 16, 2013 1:34 pm
by Owen
A particular consideration is that e.g. if you have 4 or more branches in one cache line, for some CPUs (AMD K8s are one example) the branch predictor performance degrades.

More importantly, you don't want to accidentally e.g. cause the branch predictor to evict some useful information because it saw a jump which is in a section of code rarely executed. And yes, you do see performance gains from aligning functions to cache line boundaries, because it means that more of the function can be loaded in one fetch.