Make SetLength(100 Mb) instant on Windows.
Add an optional constant SysOSAllocZeroesStartingFrom that can be defined by platform’s sysheap.inc to promise that SysOSAlloc requests of at least this size come zeroed, and use this information in AllocMem to make huge SetLengths (relatively) instant. FastMM / that mORMot thing do the same. For platforms other than Windows, the constant can often be 0 (e.g. when using Unix’s mmap(MAP_ANONYMOUS)), but do it yourselves.
Try this:
{$mode objfpc} {$longstrings on} {$typedaddress on} {$coperators on} {$modeswitch anonymousfunctions}
uses
SysUtils;
procedure Benchmark(const name: string; proc: TProcedure);
var
start, time: double;
reps, iUnit: uint32;
begin
reps := 0; start := Now;
repeat
inc(reps);
proc;
time := (Now - start) * SecsPerDay;
until not (time < 0.5);
time := time / reps;
iUnit := 0;
while (iUnit < 3) and (time < 0.9) do begin iUnit += 1; time *= 1e3; end;
writeln((name + ': ').PadRight(25), time:0:ord(time < 10), ' ', 's/ms/us/ns'.Split('/')[iUnit], '/call');
end;
begin
Benchmark('SetLength(100 Mb)',
procedure
var
a: array of byte;
begin
SetLength((@a)^, 100 * 1024 * 1024);
end);
end.
My effect: 20 ms/call → 12 µs/call.