Aggressively reallocate in dynarray_concat(_multi).
“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...