delphi - Why is dynamic array "constructor" much slower than SetLength and elements initialization? -


i comparing performances between these 2 ways of initializing dynamic array:

arr := tarray<integer>.create(1, 2, 3, 4, 5); 

and

setlength(arr, 5); arr[0] := 1; arr[1] := 2; arr[2] := 3; arr[3] := 4; arr[4] := 5; 

i've prepared test , i've noticed using array "constructor" takes twice time required other method.

test:

uses   dateutils;  function createusingsetlength() : tarray<integer>; begin   setlength(result, 5);   result[0] := 1;   result[1] := 2;   result[2] := 3;   result[3] := 4;   result[4] := 5; end; 

...

const   c_count = 10000000; var   start : tdatetime;   : integer;   arr : tarray<integer>;   ms1 : integer;   ms2 : integer; begin   start := now;   := 0;   while(i < c_count)   begin     arr := tarray<integer>.create(1, 2, 3, 4, 5);     inc(i);   end;   ms1 := millisecondsbetween(now, start);    start := now;   := 0;   while(i < c_count)   begin     arr := createusingsetlength();     inc(i);   end;   ms2 := millisecondsbetween(now, start);    showmessage('constructor = ' + inttostr(ms1) + slinebreak + 'other method = ' + inttostr(ms2)); 

testing on machine, resulting values near following:

constructor = 622

other method = 288

why array "constructor" slow?

let's take @ code generated (optimization on, win32 target, 10.2 tokyo):

project152.dpr.34: arr := tarray<integer>.create(1, 2, 3, 4, 5); 004d0d22 8d45f8           lea eax,[ebp-$08] 004d0d25 8b15b84b4000     mov edx,[$00404bb8] 004d0d2b e858bff3ff       call @dynarrayclear 004d0d30 6a05             push $05 004d0d32 8d45f8           lea eax,[ebp-$08] 004d0d35 b901000000       mov ecx,$00000001 004d0d3a 8b15b84b4000     mov edx,[$00404bb8] 004d0d40 e81fbef3ff       call @dynarraysetlength 004d0d45 83c404           add esp,$04 004d0d48 8b45f8           mov eax,[ebp-$08] 004d0d4b c70001000000     mov [eax],$00000001 004d0d51 8b45f8           mov eax,[ebp-$08] 004d0d54 c7400402000000   mov [eax+$04],$00000002 004d0d5b 8b45f8           mov eax,[ebp-$08] 004d0d5e c7400803000000   mov [eax+$08],$00000003 004d0d65 8b45f8           mov eax,[ebp-$08] 004d0d68 c7400c04000000   mov [eax+$0c],$00000004 004d0d6f 8b45f8           mov eax,[ebp-$08] 004d0d72 c7401005000000   mov [eax+$10],$00000005 004d0d79 8b55f8           mov edx,[ebp-$08] 004d0d7c 8d45fc           lea eax,[ebp-$04] 004d0d7f 8b0db84b4000     mov ecx,[$00404bb8] 004d0d85 e842bff3ff       call @dynarrayasg 

and:

project152.dpr.12: setlength(result, 5); 004d0cb2 6a05             push $05 004d0cb4 8bc3             mov eax,ebx 004d0cb6 b901000000       mov ecx,$00000001 004d0cbb 8b15b84b4000     mov edx,[$00404bb8] 004d0cc1 e89ebef3ff       call @dynarraysetlength 004d0cc6 83c404           add esp,$04 project152.dpr.13: result[0] := 1; 004d0cc9 8b03             mov eax,[ebx] 004d0ccb c70001000000     mov [eax],$00000001 project152.dpr.14: result[1] := 2; 004d0cd1 8b03             mov eax,[ebx] 004d0cd3 c7400402000000   mov [eax+$04],$00000002 project152.dpr.15: result[2] := 3; 004d0cda 8b03             mov eax,[ebx] 004d0cdc c7400803000000   mov [eax+$08],$00000003 project152.dpr.16: result[3] := 4; 004d0ce3 8b03             mov eax,[ebx] 004d0ce5 c7400c04000000   mov [eax+$0c],$00000004 project152.dpr.17: result[4] := 5; 004d0cec 8b03             mov eax,[ebx] 004d0cee c7401005000000   mov [eax+$10],$00000005 

so clear code generated "constructor" call less optimized.

as can see, "constructor" code first clears, allocates , fills anonymous array (at [ebp-$08]) , @ end, assigns arr variable (at [ebp-$04]). why slower.

in newer versions, there third way:

arr := [1, 2, 3, 4, 5]; 

but produces exact same code "constructor" syntax. can speed with:

const   c_arr = [1, 2, 3, 4, 5]; // yes, dynarray const! 

and

arr := c_arr; 

this generates dynamic array once, reference count of -1, , in loop, assignment:

project152.dpr.63: arr := c_arr; 004d0e60 8d45fc           lea eax,[ebp-$04] 004d0e63 8b15c4864d00     mov edx,[$004d86c4] 004d0e69 8b0db84b4000     mov ecx,[$00404bb8] 004d0e6f e858bef3ff       call @dynarrayasg 

remark:

but, @davidheffernan commented, in real life programming, these performance differences hardly ever noticed. don't initialize such arrays in tight loops, , in one-off situation, difference few nanoseconds, won't notice during entire run of program.

remark 2:

there seems confusion. type tarray<integer> same array of integer. neither classes or other kind of wrappers dynamic arrays. plain dynamic arrays , nothing else. constructor syntax can applied both. the difference in type compatibility. tarray<integer> can used ad-hoc type declaration, , tarray<integer> type-compatible.


Comments

Popular posts from this blog

ubuntu - PHP script to find files of certain extensions in a directory, returns populated array when run in browser, but empty array when run from terminal -

php - How can i create a user dashboard -

javascript - How to detect toggling of the fullscreen-toolbar in jQuery Mobile? -