On Wednesday, 22 December 2021 at 14:27:32 UTC, Paul Backus wrote:
> https://github.com/dlang/druntime/blob/v2.098.1/src/rt/aaA.d#L17-L27
So, we can safely put this discussion to rest, I think.
I haven't looked at the implementation of AAs or the allocator used, so I cannot tell whether it is O(1) amortized or not. You can test it by repeatedly adding/removing items near the thresholds.
A preliminary test suggests that the observed behaviour is rather wasteful, which should be a warning for anyone who considers using it in production.
It grows by a factor of 4, that is a lot of waste. It also appears to grow on deletion:
adding
changed 0 : 0
changed 6 : 8
changed 25 : 32
changed 102 : 128
changed 409 : 512
changed 1638 : 2048
changed 6553 : 8192
removing
changed 4095 : 32768
changed 1023 : 8192
changed 255 : 2048
changed 63 : 512
changed 15 : 128
changed 3 : 32
import std.stdio;
struct AA
{
Impl* impl;
};
struct Impl {
void*[] buckets;
};
void main(){
immutable N = 6554;
int[int] a;
ulong nn = 0;
writeln("adding");
for(int i = 0; i<N; i++){
auto b = a;
a[i] = i;
auto aa = cast(AA*) &a;
auto n = aa.impl.buckets.length;
if (n!=nn) {
writeln("changed ", i, " : ", nn);
nn = n;
}
}
writeln("\nremoving");
for(int i = N-1; i>=0; i--){
auto b = a;
a.remove(i);
auto aa = cast(AA*) &a;
auto n = aa.impl.buckets.length;
if (n!=nn) {
writeln("changed ", i, " : ", nn);
nn = n;
}
}
}