[HEAP.INC TIER 3 EVO] Allocate fixed arenas within variable OS chunks.
(Likely the final tier, my initial ideas only went this far.)
Trunk allocates separate OS chunks (32~256 Kb-sized) for each of the fixed sizes, and copes with the unpleasant consequences of this decision by keeping MaxKeptOSChunks
free OS chunks, not terribly succesfully. To put it in the words of mormot.core.fpcx64mm.pas
, “built-in heap.inc
... threadvar arena for small blocks tends to consume a lot of memory on multi-threaded servers”.
Instead, allocate these arenas as (almost) regular variable chunks; and make them smaller (8~64 Kb for now).
With this change, small and even not-so-small programs (and, more importantly, threads) are able to fit all of their allocations into their starting OS chunk. For example, a program (thread) that allocates 100, 200, 300, 400, and 1000 bytes performs only one SysOSAlloc
instead of 5, with 4 arenas (8 Kb each) for corresponding fixed sizes and 1 more variable chunk for 1000, all of these stuffed into the starting 64 Kb OS chunk.
Synthetic example:
var
p: array[0 .. 99] of pointer;
i: SizeInt;
begin
for i := 0 to High(p) do
p[i] := GetMem(sqr(8 + i) div 22);
writeln('Used ', GetFPCHeapStatus.CurrHeapUsed, ' / allocated ', GetFPCHeapStatus.CurrHeapSize, '.');
for i := 0 to High(p) do
FreeMem(p[i]);
end.
Trunk: used 21008 / allocated 524288 / 16 SysOSAlloc calls.
MR: used 21008 / allocated 131072 / 2 SysOSAlloc calls.