Alex
Alex

Reputation: 29

c++ for loop efficiency: body vs. afterthought

I found something interesting while on leetcode and wish someone can help explain the cause:

I was basically doing merge sort and used the fast slow pointer to find the mid pointer. Here're two versions of such code snippets:

1. update in afterthought

    for (ListNode* fast=head; 
         fast->next && fast->next->next; 
         fast = fast->next->next, slow = slow->next) { }

2. update in body

    for (ListNode* fast=head; fast->next && fast->next->next; ) {
        fast = fast->next->next;
        slow = slow->next;
    }

Why is version 2 faster than the first one?

Compiler: g++ 4.9.2

Upvotes: 1

Views: 254

Answers (1)

VolAnd
VolAnd

Reputation: 6407

It is unlikely that comma operation can significantly reduce the speed of for-loop.

I have made both variants and opened disassembly (in Visual Studio 2012) for them to see difference.

  1. looks as:

        for (ListNode* fast = head;
    0022545E  mov         eax,dword ptr [head]  
    00225461  mov         dword ptr [ebp-2Ch],eax  
            fast->next && fast->next->next;
    00225464  jmp         main+17Bh (022547Bh)  
            fast = fast->next->next, slow = slow->next) {
    00225466  mov         eax,dword ptr [ebp-2Ch]  
    00225469  mov         ecx,dword ptr [eax+4]  
    0022546C  mov         edx,dword ptr [ecx+4]  
    0022546F  mov         dword ptr [ebp-2Ch],edx  
    00225472  mov         eax,dword ptr [slow]  
    00225475  mov         ecx,dword ptr [eax+4]  
    00225478  mov         dword ptr [slow],ecx  
    0022547B  mov         eax,dword ptr [ebp-2Ch]  
    0022547E  cmp         dword ptr [eax+4],0  
    00225482  je          main+192h (0225492h)  
    00225484  mov         eax,dword ptr [ebp-2Ch]  
    00225487  mov         ecx,dword ptr [eax+4]  
    0022548A  cmp         dword ptr [ecx+4],0  
    0022548E  je          main+192h (0225492h)  
        }
    
  2. is:

        for (ListNode* fast = head; fast->next && fast->next->next;) {
    0024545E  mov         eax,dword ptr [head]  
    00245461  mov         dword ptr [ebp-2Ch],eax  
    00245464  mov         eax,dword ptr [ebp-2Ch]  
    00245467  cmp         dword ptr [eax+4],0  
    0024546B  je          main+190h (0245490h)  
    0024546D  mov         eax,dword ptr [ebp-2Ch]  
    00245470  mov         ecx,dword ptr [eax+4]  
    00245473  cmp         dword ptr [ecx+4],0  
    00245477  je          main+190h (0245490h)  
            fast = fast->next->next;
    00245479  mov         eax,dword ptr [ebp-2Ch]  
    0024547C  mov         ecx,dword ptr [eax+4]  
    0024547F  mov         edx,dword ptr [ecx+4]  
    00245482  mov         dword ptr [ebp-2Ch],edx  
            slow = slow->next;
    00245485  mov         eax,dword ptr [slow]  
    00245488  mov         ecx,dword ptr [eax+4]  
    0024548B  mov         dword ptr [slow],ecx  
        }
    

Only one jmp is the distinction. Sorry, but I cannot see significant differences, so perhaps the performance problem is not in the place of that two statements.

Upvotes: 4

Related Questions