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
Post a Comment