Skip to content

Aggressively reallocate in dynarray_concat(_multi).

Rika requested to merge runewalsh/source:daconcat into main

“Aggressively” means “not only when appending”. !493 (merged) counterpart for dynamic arrays (no one concatenates dynamic arrays, but have you heard of the chicken-and-egg problem).

In addition to the benefits of !493 (merged), there is one more optimization (sort of unavoidable if you want to reallocate). When all of these conditions are met:

  • Base type is managed;
  • Destination occurs among source arrays (Dest := A + Dest + B);
  • Dest.RefCount = 1

my version skips fpc_finalize_array on the Dest and fpc_addref_array on the part of the resulting array that contains Dest. In the common case of Length(Dest)Length(A + B), this skips a significant part of the work.

Benchmark: ArrayConcatBenchmark.pas.

My results:

x86-64                                       before         after
concat(array of int32) (avg. of 40):         32 ns/call     20 ns/call
concat_multi(array of int32) (avg. of 60):   406 ns/call    32 ns/call
concat(array of string) (avg. of 40):        576 ns/call    30 ns/call
concat_multi(array of string) (avg. of 60):  759 ns/call    63 ns/call

i386
concat(array of int32) (avg. of 40):         1422 ns/call   24 ns/call
concat_multi(array of int32) (avg. of 60):   1723 ns/call   33 ns/call
concat(array of string) (avg. of 40):        1458 ns/call   33 ns/call
concat_multi(array of string) (avg. of 60):  1963 ns/call   59 ns/call

There shouldn’t be as much speedup though, 50× on i386 looks extremely suspicious, maybe I’ll investigate later...

Merge request reports