views:

138

answers:

4

Lets consider following two codes

First:

for (int i=0;i<10000000;i++)
{
    char* tab = new char[500];
    delete[] tab;
}

Second:

for (int i=0;i<10000000;i++)
{
    char tab[500];
}

The peak memory usage is almost the same, but the second code runs about 20 times faster than the first one.

Question
Is it because in first code array is stored on heap, and in the second one array is stored on stack?

+5  A: 

Is it because in first code array is stored on heap, and in the second one array is stored on stack?

Yes, Stack allocation is much faster as all the second code sample is doing is moving (adding/subtracting) the stack pointer rather than manipulating the heap.

If you want to know more, these two questions cover the subject

Yacoby
+2  A: 

Yes. allocating arrays on the heap is much, much slower than creating them automatically. The former may involve a system call, and will always involve manipulating heap structures, whereas the latter simply adjusts the stack pointer.

anon
+1  A: 

Just to confirm 2 previous answers, when profiling such code (in Visual Studio), and looking at assembly code, first one calls operator new and second does not which means its allocated automatically on stack.

Here's how it looks

int _tmain(int argc, _TCHAR* argv[])
{
00401000  push        ebp  
00401001  mov         ebp,esp 
00401003  sub         esp,304h 
00401009  push        ebx  
0040100A  push        esi  
0040100B  push        edi  
0040100C  lea         edi,[ebp-304h] 
00401012  mov         ecx,0C1h 
00401017  mov         eax,0CCCCCCCCh 
0040101C  rep stos    dword ptr es:[edi] 
    for (int i=0;i<10000;i++)
0040101E  mov         dword ptr [i],0 
00401025  jmp         wmain+30h (401030h) 
00401027  mov         eax,dword ptr [i] 
0040102A  add         eax,1 
0040102D  mov         dword ptr [i],eax 
00401030  cmp         dword ptr [i],2710h 
00401037  jge         wmain+6Fh (40106Fh) 
    {
        char* tab = new char[500];
00401039  push        1F4h 
0040103E  call        operator new[] (4010F0h) 
00401043  add         esp,4 
00401046  mov         dword ptr [ebp-300h],eax 
0040104C  mov         eax,dword ptr [ebp-300h] 
00401052  mov         dword ptr [tab],eax 
        delete[] tab;
00401055  mov         eax,dword ptr [tab] 
00401058  mov         dword ptr [ebp-2F4h],eax 
0040105E  mov         ecx,dword ptr [ebp-2F4h] 
00401064  push        ecx  
00401065  call        operator delete[] (401104h) 
0040106A  add         esp,4 
    }
0040106D  jmp         wmain+27h (401027h) 

    for (int i=0;i<10000;i++)
0040106F  mov         dword ptr [i],0 
00401076  jmp         wmain+81h (401081h) 
00401078  mov         eax,dword ptr [i] 
0040107B  add         eax,1 
0040107E  mov         dword ptr [i],eax 
00401081  cmp         dword ptr [i],2710h 
00401088  jge         wmain+8Ch (40108Ch) 
    {
        char tab[500];
    }
0040108A  jmp         wmain+78h (401078h) 

    return 0;
0040108C  xor         eax,eax 
}
zveljkovic
+1  A: 

Did you try it running with optimizations turned on? I would be very surprised if there were any difference at all after the optimizer kicks in. In fact, I would expect the optimizer to remove the loop altogether in both cases.

Nemanja Trifunovic
I haven't tried to compile it with optimizations, because it wasn't the purpose. I just wanted to be sure why the second code is much faster.
Tomek Tarczynski
Why would you expect it to remove the new[]/delete[] loop? Optimizing out a call to a function with external linkage (and side effects) sounds like a dangerous thing to do.
bk1e
It is not a function - just a loop that obviously does nothing.
Nemanja Trifunovic
Technically, `new` indeed is not a function, but it does call one. bk1e incorrectly assumes that function has side effects. A non-default one could, but that makes the entire timing meaningless.
MSalters