473,395 Members | 2,437 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,395 software developers and data experts.

Array Performance: fix-size vs dynamic

In following codes, both the places 'p' is a global variable. In 1st case it's an array and 2nd case it's a pointer to an array. Do we get any performance benefit, while accessing 'p[ i ]' in the fixed size case ?

Fixed size array:
============
int p[1000];
void main ( )
{
for(int i = 0; i < 1000; i++)
p[ i ] = i;
}

Dynamic array:
===========
int *p = new int[1000];
void main ( )
{
for(int i = 0; i < 1000; i++)
p[ i ] = i;
}
Jul 6 '10 #1

✓ answered by Banfa

Take this program

Expand|Select|Wrap|Line Numbers
  1. int ugarray[5];
  2. int igarray[5] = {10,9,8,7,6};
  3.  
  4. int get1(int *array);
  5.  
  6. int main()
  7. {
  8.     int sarray[5];
  9.     int* harray = new int[5];
  10.     int ix;
  11.  
  12.     ugarray[1] = 4;
  13.     igarray[1] = 4;
  14.     sarray[1] = 4;
  15.     harray[1] = 4;
  16.  
  17.     ix = ugarray[1];
  18.     ix = igarray[1];
  19.     ix = sarray[1];
  20.     ix = harray[1];
  21.  
  22.     get1(ugarray);
  23.     get1(igarray);
  24.     get1(sarray);
  25.     get1(harray);
  26.  
  27.     delete harray;
  28.  
  29.   return 0;
  30. }
  31.  
  32. int get1(int *array)
  33. {
  34.     return array[1];
  35. }
  36.  
It creates all types of arrays and accesses them for both read and write.

Take a look at the assembler
Expand|Select|Wrap|Line Numbers
  1. int main()
  2. {
  3. 0042D660  push        ebp  
  4. 0042D661  mov         ebp,esp 
  5. 0042D663  sub         esp,10Ch 
  6. 0042D669  push        ebx  
  7. 0042D66A  push        esi  
  8. 0042D66B  push        edi  
  9. 0042D66C  lea         edi,[ebp-10Ch] 
  10. 0042D672  mov         ecx,43h 
  11. 0042D677  mov         eax,0CCCCCCCCh 
  12. 0042D67C  rep stos    dword ptr es:[edi] 
  13.     int sarray[5];
  14.     int* harray = new int[5];
  15. 0042D67E  push        14h  
  16. 0042D680  call        operator new (42C072h) 
  17. 0042D685  add         esp,4 
  18. 0042D688  mov         dword ptr [ebp-108h],eax 
  19. 0042D68E  mov         eax,dword ptr [ebp-108h] 
  20. 0042D694  mov         dword ptr [harray],eax 
  21.     int ix;
  22.  
  23.     ugarray[1] = 4;
  24. 0042D697  mov         dword ptr [ugarray+4 (495504h)],4 
  25.     igarray[1] = 4;
  26. 0042D6A1  mov         dword ptr [igarray+4 (494004h)],4 
  27.     sarray[1] = 4;
  28. 0042D6AB  mov         dword ptr [ebp-14h],4 
  29.     harray[1] = 4;
  30. 0042D6B2  mov         eax,dword ptr [harray] 
  31. 0042D6B5  mov         dword ptr [eax+4],4 
  32.  
  33.     ix = ugarray[1];
  34. 0042D6BC  mov         eax,dword ptr [ugarray+4 (495504h)] 
  35. 0042D6C1  mov         dword ptr [ix],eax 
  36.     ix = igarray[1];
  37. 0042D6C4  mov         eax,dword ptr [igarray+4 (494004h)] 
  38. 0042D6C9  mov         dword ptr [ix],eax 
  39.     ix = sarray[1];
  40. 0042D6CC  mov         eax,dword ptr [ebp-14h] 
  41. 0042D6CF  mov         dword ptr [ix],eax 
  42.     ix = harray[1];
  43. 0042D6D2  mov         eax,dword ptr [harray] 
  44. 0042D6D5  mov         ecx,dword ptr [eax+4] 
  45. 0042D6D8  mov         dword ptr [ix],ecx 
  46.  
  47.     get1(ugarray);
  48. 0042D6DB  push        offset ugarray (495500h) 
  49. 0042D6E0  call        get1 (42C32Eh) 
  50. 0042D6E5  add         esp,4 
  51.     get1(igarray);
  52. 0042D6E8  push        offset igarray (494000h) 
  53. 0042D6ED  call        get1 (42C32Eh) 
  54. 0042D6F2  add         esp,4 
  55.     get1(sarray);
  56. 0042D6F5  lea         eax,[sarray] 
  57. 0042D6F8  push        eax  
  58. 0042D6F9  call        get1 (42C32Eh) 
  59. 0042D6FE  add         esp,4 
  60.     get1(harray);
  61. 0042D701  mov         eax,dword ptr [harray] 
  62. 0042D704  push        eax  
  63. 0042D705  call        get1 (42C32Eh) 
  64. 0042D70A  add         esp,4 
  65.  
  66.     delete harray;
  67. 0042D70D  mov         eax,dword ptr [harray] 
  68. 0042D710  mov         dword ptr [ebp-0FCh],eax 
  69. 0042D716  mov         ecx,dword ptr [ebp-0FCh] 
  70. 0042D71C  push        ecx  
  71. 0042D71D  call        operator delete (42B5EBh) 
  72. 0042D722  add         esp,4 
  73.  
  74.   return 0;
  75. 0042D725  xor         eax,eax 
  76. }
  77. 0042D727  push        edx  
  78. 0042D728  mov         ecx,ebp 
  79. 0042D72A  push        eax  
  80. 0042D72B  lea         edx,[ (42D74Ch)] 
  81. 0042D731  call        @ILT+1470(@_RTC_CheckStackVars@8) (42B5C3h) 
  82. 0042D736  pop         eax  
  83. 0042D737  pop         edx  
  84. 0042D738  pop         edi  
  85. 0042D739  pop         esi  
  86. 0042D73A  pop         ebx  
  87. 0042D73B  add         esp,10Ch 
  88. 0042D741  cmp         ebp,esp 
  89. 0042D743  call        @ILT+3420(__RTC_CheckEsp) (42BD61h) 
  90. 0042D748  mov         esp,ebp 
  91. 0042D74A  pop         ebp  
  92. 0042D74B  ret 
And for get1
Expand|Select|Wrap|Line Numbers
  1. int get1(int *array)
  2. {
  3. 0042D860  push        ebp  
  4. 0042D861  mov         ebp,esp 
  5. 0042D863  sub         esp,0C0h 
  6. 0042D869  push        ebx  
  7. 0042D86A  push        esi  
  8. 0042D86B  push        edi  
  9. 0042D86C  lea         edi,[ebp-0C0h] 
  10. 0042D872  mov         ecx,30h 
  11. 0042D877  mov         eax,0CCCCCCCCh 
  12. 0042D87C  rep stos    dword ptr es:[edi] 
  13.     return array[1];
  14. 0042D87E  mov         eax,dword ptr [array] 
  15. 0042D881  mov         eax,dword ptr [eax+4] 
  16. }
  17. 0042D884  pop         edi  
  18. 0042D885  pop         esi  
  19. 0042D886  pop         ebx  
  20. 0042D887  mov         esp,ebp 
  21. 0042D889  pop         ebp  
  22. 0042D88A  ret     
  23.  
A number of things are obvious (but note this only holds for the platform I am using here, Windows XP Visual Studio 2008).

uninitialised global, initialised global and stack variables all use the same instructions for access. A heap array using these instructions too but has to start by loading the pointer to the array. That is natural the heap array is accessed via an intermediary variable.

This might suggest that heap access will be a lot slower, it appears that it take 2 instructions to read where everything else takes 1. However a good optimising compiler is going to notice the constant loading of the pointer in harray and will endeavour, and normally succeed to optimise away most of them just leaving the read/write instruction making access to the heap about the same as anywhere else.

Next look at get1. Everyone can pass their pointer to get1 and it executes exactly the same set of instructions. My point here is that you rarely operate directly on data objects, you most often are passing them to other functions via a pointer and once you have done that you really have completely levelled the playing field.

9 5396
code green
1,726 Expert 1GB
The first would allocate memoery on the stack,
The second would allocate memory on the heap.
Stack access should be faster.
Why not run a benchmark test
Expand|Select|Wrap|Line Numbers
  1. int main() 
  2.     clock_t start = clock(); 
  3.     int p[10000];
  4.     for(int i = 0; i < 10000; i++)
  5.         p[ i ] = i;
  6.  
  7.     clock_t duration = clock() - start; 
  8.     cout << "stack time " << duration << "\n"; 
  9.  
  10.     start = clock(); 
  11.     int *p = new int[10000];
  12.     for(int i = 0; i < 10000; i++)
  13.         p[ i ] = i;
  14.  
  15.     duration = clock() - start; 
  16.     cout << "heap time " << duration << "\n"; 
  17.  
Jul 6 '10 #2
Banfa
9,065 Expert Mod 8TB
Stack access should be faster.
Complete rubbish. Heap and stack access times are platform dependent, since platforms are not even required to have them.

However the majority of platforms that have a heap and a stack use the same type of memory to store them and therefore the access times will be the same.

It may take marginally longer to allocate data from the heap.

All as verified by running you code on my PC.
Jul 6 '10 #3
code green
1,726 Expert 1GB
Complete rubbish.
It may take marginally longer to allocate data from the heap.
Yes I didn't read the post properly and was thinking more about memory allocation instead os access
Jul 6 '10 #4
@Banfa
Please note that here the comparison is not happening between stack and heap. But the data segment and the heap.
For this case, assume that we are not accounting the original heap allocation.
'p' in the 1st case is at data segment; thus its address would be known by compiler.
'p' in the 2nd case at heap segment is also known; but it's pointing to some location.
I was just wondering at assembly level, is it possible that the data segment 'p' might become a little faster ?
I am unsure about it.
Jul 9 '10 #5
Banfa
9,065 Expert Mod 8TB
@Banfa
Please note that here the comparison is not happening between stack and heap. But the data segment and the heap.
Not really relevant or if anything even less relevant. The "data segment" can mean a number of things but most commonly either
  1. The area of memory containing heap segment and uninitialised program global/static variables (which will be initialised to 0) called bss and initialised program global/static variables called data.
  2. Initialised program global/static variables.

Sometimes if using definition 1 the stack segment is included as part of the data segment. Regardless all of those segments generally (and for a PC are specifically) stored in the same type of memory. Once you have the pointer to that memory the method used to allocate that pointer, be it stack, heap or program data is irrelevance to the speed at which the memory is accessed.
Jul 9 '10 #6
Banfa
9,065 Expert Mod 8TB
Take this program

Expand|Select|Wrap|Line Numbers
  1. int ugarray[5];
  2. int igarray[5] = {10,9,8,7,6};
  3.  
  4. int get1(int *array);
  5.  
  6. int main()
  7. {
  8.     int sarray[5];
  9.     int* harray = new int[5];
  10.     int ix;
  11.  
  12.     ugarray[1] = 4;
  13.     igarray[1] = 4;
  14.     sarray[1] = 4;
  15.     harray[1] = 4;
  16.  
  17.     ix = ugarray[1];
  18.     ix = igarray[1];
  19.     ix = sarray[1];
  20.     ix = harray[1];
  21.  
  22.     get1(ugarray);
  23.     get1(igarray);
  24.     get1(sarray);
  25.     get1(harray);
  26.  
  27.     delete harray;
  28.  
  29.   return 0;
  30. }
  31.  
  32. int get1(int *array)
  33. {
  34.     return array[1];
  35. }
  36.  
It creates all types of arrays and accesses them for both read and write.

Take a look at the assembler
Expand|Select|Wrap|Line Numbers
  1. int main()
  2. {
  3. 0042D660  push        ebp  
  4. 0042D661  mov         ebp,esp 
  5. 0042D663  sub         esp,10Ch 
  6. 0042D669  push        ebx  
  7. 0042D66A  push        esi  
  8. 0042D66B  push        edi  
  9. 0042D66C  lea         edi,[ebp-10Ch] 
  10. 0042D672  mov         ecx,43h 
  11. 0042D677  mov         eax,0CCCCCCCCh 
  12. 0042D67C  rep stos    dword ptr es:[edi] 
  13.     int sarray[5];
  14.     int* harray = new int[5];
  15. 0042D67E  push        14h  
  16. 0042D680  call        operator new (42C072h) 
  17. 0042D685  add         esp,4 
  18. 0042D688  mov         dword ptr [ebp-108h],eax 
  19. 0042D68E  mov         eax,dword ptr [ebp-108h] 
  20. 0042D694  mov         dword ptr [harray],eax 
  21.     int ix;
  22.  
  23.     ugarray[1] = 4;
  24. 0042D697  mov         dword ptr [ugarray+4 (495504h)],4 
  25.     igarray[1] = 4;
  26. 0042D6A1  mov         dword ptr [igarray+4 (494004h)],4 
  27.     sarray[1] = 4;
  28. 0042D6AB  mov         dword ptr [ebp-14h],4 
  29.     harray[1] = 4;
  30. 0042D6B2  mov         eax,dword ptr [harray] 
  31. 0042D6B5  mov         dword ptr [eax+4],4 
  32.  
  33.     ix = ugarray[1];
  34. 0042D6BC  mov         eax,dword ptr [ugarray+4 (495504h)] 
  35. 0042D6C1  mov         dword ptr [ix],eax 
  36.     ix = igarray[1];
  37. 0042D6C4  mov         eax,dword ptr [igarray+4 (494004h)] 
  38. 0042D6C9  mov         dword ptr [ix],eax 
  39.     ix = sarray[1];
  40. 0042D6CC  mov         eax,dword ptr [ebp-14h] 
  41. 0042D6CF  mov         dword ptr [ix],eax 
  42.     ix = harray[1];
  43. 0042D6D2  mov         eax,dword ptr [harray] 
  44. 0042D6D5  mov         ecx,dword ptr [eax+4] 
  45. 0042D6D8  mov         dword ptr [ix],ecx 
  46.  
  47.     get1(ugarray);
  48. 0042D6DB  push        offset ugarray (495500h) 
  49. 0042D6E0  call        get1 (42C32Eh) 
  50. 0042D6E5  add         esp,4 
  51.     get1(igarray);
  52. 0042D6E8  push        offset igarray (494000h) 
  53. 0042D6ED  call        get1 (42C32Eh) 
  54. 0042D6F2  add         esp,4 
  55.     get1(sarray);
  56. 0042D6F5  lea         eax,[sarray] 
  57. 0042D6F8  push        eax  
  58. 0042D6F9  call        get1 (42C32Eh) 
  59. 0042D6FE  add         esp,4 
  60.     get1(harray);
  61. 0042D701  mov         eax,dword ptr [harray] 
  62. 0042D704  push        eax  
  63. 0042D705  call        get1 (42C32Eh) 
  64. 0042D70A  add         esp,4 
  65.  
  66.     delete harray;
  67. 0042D70D  mov         eax,dword ptr [harray] 
  68. 0042D710  mov         dword ptr [ebp-0FCh],eax 
  69. 0042D716  mov         ecx,dword ptr [ebp-0FCh] 
  70. 0042D71C  push        ecx  
  71. 0042D71D  call        operator delete (42B5EBh) 
  72. 0042D722  add         esp,4 
  73.  
  74.   return 0;
  75. 0042D725  xor         eax,eax 
  76. }
  77. 0042D727  push        edx  
  78. 0042D728  mov         ecx,ebp 
  79. 0042D72A  push        eax  
  80. 0042D72B  lea         edx,[ (42D74Ch)] 
  81. 0042D731  call        @ILT+1470(@_RTC_CheckStackVars@8) (42B5C3h) 
  82. 0042D736  pop         eax  
  83. 0042D737  pop         edx  
  84. 0042D738  pop         edi  
  85. 0042D739  pop         esi  
  86. 0042D73A  pop         ebx  
  87. 0042D73B  add         esp,10Ch 
  88. 0042D741  cmp         ebp,esp 
  89. 0042D743  call        @ILT+3420(__RTC_CheckEsp) (42BD61h) 
  90. 0042D748  mov         esp,ebp 
  91. 0042D74A  pop         ebp  
  92. 0042D74B  ret 
And for get1
Expand|Select|Wrap|Line Numbers
  1. int get1(int *array)
  2. {
  3. 0042D860  push        ebp  
  4. 0042D861  mov         ebp,esp 
  5. 0042D863  sub         esp,0C0h 
  6. 0042D869  push        ebx  
  7. 0042D86A  push        esi  
  8. 0042D86B  push        edi  
  9. 0042D86C  lea         edi,[ebp-0C0h] 
  10. 0042D872  mov         ecx,30h 
  11. 0042D877  mov         eax,0CCCCCCCCh 
  12. 0042D87C  rep stos    dword ptr es:[edi] 
  13.     return array[1];
  14. 0042D87E  mov         eax,dword ptr [array] 
  15. 0042D881  mov         eax,dword ptr [eax+4] 
  16. }
  17. 0042D884  pop         edi  
  18. 0042D885  pop         esi  
  19. 0042D886  pop         ebx  
  20. 0042D887  mov         esp,ebp 
  21. 0042D889  pop         ebp  
  22. 0042D88A  ret     
  23.  
A number of things are obvious (but note this only holds for the platform I am using here, Windows XP Visual Studio 2008).

uninitialised global, initialised global and stack variables all use the same instructions for access. A heap array using these instructions too but has to start by loading the pointer to the array. That is natural the heap array is accessed via an intermediary variable.

This might suggest that heap access will be a lot slower, it appears that it take 2 instructions to read where everything else takes 1. However a good optimising compiler is going to notice the constant loading of the pointer in harray and will endeavour, and normally succeed to optimise away most of them just leaving the read/write instruction making access to the heap about the same as anywhere else.

Next look at get1. Everyone can pass their pointer to get1 and it executes exactly the same set of instructions. My point here is that you rarely operate directly on data objects, you most often are passing them to other functions via a pointer and once you have done that you really have completely levelled the playing field.
Jul 9 '10 #7
Hi Banfa,
This was the exact point i was trying to make.
In my particular requirement, I have the ability to use the data segment directly. If I use heap segment with global pointer, then as your assembly suggests, it will create one extra indirection.
Thus the heap access will be slower compare to the direct data segment access.

get1() example is naturally same for all segments, because we deal with a simple pointer. But I don't intend to do that.

Thanks.
Jul 9 '10 #8
Banfa
9,065 Expert Mod 8TB
My point is your trying to decided which is the "best" memory to use is mainly a waste of time unless you actually have 2 different banks of memory with different access times. I have worked with processors that had a small amount of on-board RAM you could use to hold some variables. In that situation there was a significant difference in access speed to the different memory banks.

Efficiency of the algorithm used is much more likely to have an effect than choosing the "right" memory allocation technique.

Accessing an array directly rather than through a pointer may be ever so marginally faster but you would be needing to do an extremely large number of accesses. By definition a heap array is always accessed through a pointer but as I said most of the time a stack or static data array is also accessed through a pointer too eliminating difference.
Jul 9 '10 #9
No, you got me wrong. I am not deciding which is the better memory to use by this single example.

My requirement was something like following:
I need an array which will keep record of some info.
The array length is decided before the program executes, so naturally the choice will go for static array on data segment.
At the same time, the array length has to be configurable by user before the program starts, so naturally the choice will go for heap segment (otherwise we need to always go and edit the file and recompile it);

The code needs to be highly optimized. So I was wondering if heap doesn't have any performance difference compared to data segment, then I will straight away choose heap segment itself.
Hope I made my 'complex' requirement clear. :)
Jul 9 '10 #10

Sign in to post your reply or Sign up for a free account.

Similar topics

7
by: guy | last post by:
from using FxCop and reading MSDN i understand that i should not use properties to access arrays, i should use methods instead, however when i try the code below the MSIL for method and property...
3
by: Andrew Phillipo | last post by:
In IE5 I am working with a lot of code that uses Array.push() as well as for(var i in myArray) {} Great - so I'm fixing the Array.prototype.push function for browsers without it. That...
2
by: Frank Pool | last post by:
Hi, I have on large threedimensional array int largeArray; In a particular function I only need a part of this array So I'm using a new variable and assign it the follwoing way: int...
3
by: Stuart | last post by:
I have a Struct like this: public struct SocketStruct { public int SerialNo1; public long SerialNo2; public int status; public byte SomeData;
20
by: John Mark Howell | last post by:
I had a customer call about some C# code they had put together that was handling some large arrays. The performance was rather poor. The C# code runs in about 22 seconds and the equivalent...
4
by: Gregory.A.Book | last post by:
I'm working with displaying and manipulating very large image sets. The program handles anything from 2D images to 4D RGB volumes in a time-series. I've been using dynamically allocated arrays to...
3
by: google | last post by:
I am trying to complete a javascript application and am having problems with code similar to that show below. Much testing has shown that Firefox finishes the code shown in around 0.25 secs but...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.