• Josh Bleecher Snyder's avatar
    runtime: preallocate some overflow buckets · 94e44a9c
    Josh Bleecher Snyder authored
    When allocating a non-small array of buckets for a map,
    also preallocate some overflow buckets.
    
    The estimate of the number of overflow buckets
    is based on a simulation of putting mid=(low+high)/2 elements
    into a map, where low is the minimum number of elements
    needed to reach this value of b (according to overLoadFactor),
    and high is the maximum number of elements possible
    to put in this value of b (according to overLoadFactor).
    This estimate is surprisingly reliable and accurate.
    
    The number of overflow buckets needed is quadratic,
    for a fixed value of b.
    Using this mid estimate means that we will overallocate a few
    too many overflow buckets when the actual number of elements is near low,
    and underallocate significantly too few overflow buckets
    when the actual number of elements is near high.
    
    The mechanism introduced in this CL can be re-used for
    other overflow bucket optimizations.
    
    For example, given an initial size hint,
    we could estimate quite precisely the number of overflow buckets.
    This is #19931.
    
    We could also change from "non-nil means end-of-list"
    to "pointer-to-hmap.buckets means end-of-list",
    and then create a linked list of reusable overflow buckets
    when they are freed by map growth.
    That is #19992.
    
    We could also use a similar mechanism to do bulk allocation
    of overflow buckets.
    All these uses can co-exist with only the one additional pointer
    in mapextra, given a little care.
    
    name                  old time/op    new time/op    delta
    MapPopulate/1-8         60.1ns ± 2%    60.3ns ± 2%     ~     (p=0.278 n=19+20)
    MapPopulate/10-8         577ns ± 1%     578ns ± 1%     ~     (p=0.140 n=20+20)
    MapPopulate/100-8       8.06µs ± 1%    8.19µs ± 1%   +1.67%  (p=0.000 n=20+20)
    MapPopulate/1000-8       104µs ± 1%     104µs ± 1%     ~     (p=0.317 n=20+20)
    MapPopulate/10000-8      891µs ± 1%     888µs ± 1%     ~     (p=0.101 n=19+20)
    MapPopulate/100000-8    8.61ms ± 1%    8.58ms ± 0%   -0.34%  (p=0.009 n=20+17)
    
    name                  old alloc/op   new alloc/op   delta
    MapPopulate/1-8          0.00B          0.00B          ~     (all equal)
    MapPopulate/10-8          179B ± 0%      179B ± 0%     ~     (all equal)
    MapPopulate/100-8       3.33kB ± 0%    3.38kB ± 0%   +1.48%  (p=0.000 n=20+16)
    MapPopulate/1000-8      55.5kB ± 0%    53.4kB ± 0%   -3.84%  (p=0.000 n=19+20)
    MapPopulate/10000-8      432kB ± 0%     428kB ± 0%   -1.06%  (p=0.000 n=19+20)
    MapPopulate/100000-8    3.65MB ± 0%    3.62MB ± 0%   -0.70%  (p=0.000 n=20+20)
    
    name                  old allocs/op  new allocs/op  delta
    MapPopulate/1-8           0.00           0.00          ~     (all equal)
    MapPopulate/10-8          1.00 ± 0%      1.00 ± 0%     ~     (all equal)
    MapPopulate/100-8         18.0 ± 0%      17.0 ± 0%   -5.56%  (p=0.000 n=20+20)
    MapPopulate/1000-8        96.0 ± 0%      72.6 ± 1%  -24.38%  (p=0.000 n=20+20)
    MapPopulate/10000-8        625 ± 0%       319 ± 0%  -48.86%  (p=0.000 n=20+20)
    MapPopulate/100000-8     6.23k ± 0%     4.00k ± 0%  -35.79%  (p=0.000 n=20+20)
    
    Change-Id: I01f41cb1374bdb99ccedbc00d04fb9ae43daa204
    Reviewed-on: https://go-review.googlesource.com/40979
    Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
    TryBot-Result: Gobot Gobot <gobot@golang.org>
    Reviewed-by: 's avatarKeith Randall <khr@golang.org>
    94e44a9c
Name
Last commit
Last update
..
archive Loading commit data...
bufio Loading commit data...
builtin Loading commit data...
bytes Loading commit data...
cmd Loading commit data...
compress Loading commit data...
container Loading commit data...
context Loading commit data...
crypto Loading commit data...
database/sql Loading commit data...
debug Loading commit data...
encoding Loading commit data...
errors Loading commit data...
expvar Loading commit data...
flag Loading commit data...
fmt Loading commit data...
go Loading commit data...
hash Loading commit data...
html Loading commit data...
image Loading commit data...
index/suffixarray Loading commit data...
internal Loading commit data...
io Loading commit data...
log Loading commit data...
math Loading commit data...
mime Loading commit data...
net Loading commit data...
os Loading commit data...
path Loading commit data...
plugin Loading commit data...
reflect Loading commit data...
regexp Loading commit data...
runtime Loading commit data...
sort Loading commit data...
strconv Loading commit data...
strings Loading commit data...
sync Loading commit data...
syscall Loading commit data...
testing Loading commit data...
text Loading commit data...
time Loading commit data...
unicode Loading commit data...
unsafe Loading commit data...
vendor/golang_org/x Loading commit data...
Make.dist Loading commit data...
all.bash Loading commit data...
all.bat Loading commit data...
all.rc Loading commit data...
androidtest.bash Loading commit data...
bootstrap.bash Loading commit data...
buildall.bash Loading commit data...
clean.bash Loading commit data...
clean.bat Loading commit data...
clean.rc Loading commit data...
cmp.bash Loading commit data...
iostest.bash Loading commit data...
make.bash Loading commit data...
make.bat Loading commit data...
make.rc Loading commit data...
naclmake.bash Loading commit data...
nacltest.bash Loading commit data...
race.bash Loading commit data...
race.bat Loading commit data...
run.bash Loading commit data...
run.bat Loading commit data...
run.rc Loading commit data...