In fact it can be a serious bottleneck !!!
1 - A copy operation may happen even if the block wasn't resized (same size) ... weak-ref :
procedure DynArraySetLength(var a: Pointer; typeInfo: Pointer; dimCnt: NativeInt; lengthVec: PNativeint);
//....
if SysHasWeakRef(PTypeInfo(ElTypeInfo)) then
begin
if newLength < oldLength then
minLength := newLength
else
minLength := oldLength;
GetMem(pp, neededSize);
FillChar((PByte(pp) + SizeOf(TDynArrayRec))^, minLength * elSize, 0);
if p <> nil then
begin
// ---> here <---
MoveArray(PByte(pp) + SizeOf(TDynArrayRec),
PByte(p) + SizeOf(TDynArrayRec), ElTypeInfo, minLength);
if newLength < oldLength then
FinalizeArray(PByte(p) + SizeOf(TDynArrayRec) + newLength*elSize, ElTypeInfo, oldLength - newLength);
FreeMem(p);
end;
end
2 - The operation executes on O(n) when the array is multidimensional :
// Take care of the inner dimensions, if any
if dimCnt > 1 then
begin
Inc(lengthVec);
Dec(dimCnt);
i := 0;
try
while i < newLength do
begin
DynArraySetLength(PPointerArray(p)[i], ElTypeInfo, dimCnt, lengthVec);
Inc(i);
end;
except
// Free arrays on exception
for j := 0 to i do
_DynArrayClear(PPointerArray(p)[j], ElTypeInfo);
_DynArrayClear(p, typeInfo);
raise;
end;
end;
//---------------------------------
var
LArray: array of array of Integer;
begin
SetLength(LArray, 100,10);
SetLength(LArray, 100,10); // DynArraySetLength x100
end;
3 - The function can ruin the cache ! because it dereferences some rtti data and it relies on MM to check for the block size. If the check was implemented inside the function than we won't dereference any unnecessary data.
4 - Adding a simple check to compare old vs new length will be much better and avoids all the issues above.
I think that you should fire a case.