Use atomic operations on flags field to make sure we aren't
losing a flag update during parallel map operations.
R=golang-dev, dave, r
CC=golang-dev
https://golang.org/cl/8377046
This changes the map lookup behavior for string maps with 2-8 keys.
There was already previously a fastpath for 0 items and 1 item.
Now, if a string-keyed map has <= 8 items, first check all the
keys for length first. If only one has the right length, then
just check it for equality and avoid hashing altogether. Once
the map has more than 8 items, always hash like normal.
I don't know why some of the other non-string map benchmarks
got faster. This was with benchtime=2s, multiple times. I haven't
anything else getting slower, though.
benchmark old ns/op new ns/op delta
BenchmarkHashStringSpeed 37 34 -8.20%
BenchmarkHashInt32Speed 32 29 -10.67%
BenchmarkHashInt64Speed 31 27 -12.82%
BenchmarkHashStringArraySpeed 105 99 -5.43%
BenchmarkMegMap 274206 255153 -6.95%
BenchmarkMegOneMap 27 23 -14.80%
BenchmarkMegEqMap 148332 116089 -21.74%
BenchmarkMegEmptyMap 4 3 -12.72%
BenchmarkSmallStrMap 22 22 -0.89%
BenchmarkMapStringKeysEight_32 42 23 -43.71%
BenchmarkMapStringKeysEight_64 55 23 -56.96%
BenchmarkMapStringKeysEight_1M 279688 24 -99.99%
BenchmarkIntMap 16 15 -10.18%
BenchmarkRepeatedLookupStrMapKey32 40 37 -8.15%
BenchmarkRepeatedLookupStrMapKey1M 287918 272980 -5.19%
BenchmarkNewEmptyMap 156 130 -16.67%
R=golang-dev, khr
CC=golang-dev
https://golang.org/cl/7641057
Doing grow work on reads is not multithreaded safe.
Changed code to do grow work only on inserts & deletes.
This is a short-term fix, eventually we'll want to do
grow work in parallel to recover the space of the old
table.
Fixes#5120.
R=bradfitz, khr
CC=golang-dev
https://golang.org/cl/8242043
Motivated by garbage profiling in HTTP benchmarks. This
changes means new empty maps are just one small allocation
(the HMap) instead the HMap + the relatively larger h->buckets
allocation. This helps maps which remain empty throughout
their life.
benchmark old ns/op new ns/op delta
BenchmarkNewEmptyMap 196 107 -45.41%
benchmark old allocs new allocs delta
BenchmarkNewEmptyMap 2 1 -50.00%
benchmark old bytes new bytes delta
BenchmarkNewEmptyMap 195 50 -74.36%
R=khr, golang-dev, r
CC=golang-dev
https://golang.org/cl/7722046
Adds the new debugging constant 'checkgc'. If its value is non-zero
all calls to mallocgc() from hashmap.c will start a garbage collection.
Fixes#5074.
R=golang-dev, khr
CC=golang-dev, rsc
https://golang.org/cl/7663051
Hashtable is arranged as an array of
8-entry buckets with chained overflow.
Each bucket has 8 extra hash bits
per key to provide quick lookup within
a bucket. Table is grown incrementally.
Update #3885
Go time drops from 0.51s to 0.34s.
R=r, rsc, m3b, dave, bradfitz, khr, ugorji, remyoudompheng
CC=golang-dev
https://golang.org/cl/7504044
Inserting a key-value pair into a hashmap storing keys or values
indirectly can cause the garbage collector to find the hashmap in
an inconsistent state.
Fixes#5074.
R=golang-dev, minux.ma, rsc
CC=golang-dev
https://golang.org/cl/7913043
When a race happens inside of runtime (chan, slice, etc),
currently reports contain only user file:line.
If the line contains a complex expression,
it's difficult to figure out where the race exactly.
This change adds one more top frame with exact
runtime function (e.g. runtime.chansend, runtime.mapaccess).
R=golang-dev
CC=golang-dev
https://golang.org/cl/6851125
This CL makes the runtime understand that the type of
the len or cap of a map, slice, or string is 'int', not 'int32',
and it is also careful to distinguish between function arguments
and results of type 'int' vs type 'int32'.
In the runtime, the new typedefs 'intgo' and 'uintgo' refer
to Go int and uint. The C types int and uint continue to be
unavailable (cause intentional compile errors).
This CL does not change the meaning of int, but it should make
the eventual change of the meaning of int on amd64 a bit
smoother.
Update #2188.
R=iant, r, dave, remyoudompheng
CC=golang-dev
https://golang.org/cl/6551067
This can only happen if the hash function we're using is getting
far more than it's fair share of collisions, but that has happened
to us repeatedly as we've expanded the allowed use cases for
hash tables (issue 1544, issue 2609, issue 2630, issue 2883, issue 3695).
Maybe this will help the next time we try something new.
R=golang-dev, r
CC=golang-dev
https://golang.org/cl/6306083
It's sad to introduce a new macro, but rnd shows up consistently
in profiles, and the function call overwhelms the two arithmetic
instructions it performs.
R=r
CC=golang-dev
https://golang.org/cl/6260051
This is from CL 5451105 but was dropped from that CL.
See also CL 6137051.
The only change compared to 5451105 is to check for
h != nil in reflect·mapiterinit; allowing use of nil maps
must have happened after that original CL.
Fixes#3573.
R=golang-dev, dave, r
CC=golang-dev
https://golang.org/cl/6215078
This patch adds a hash seed to the Hmap struct. Each seed is
initialized by runtime.fastrand1(). This is the first step of a
solution to issue 2630. Fastrand1 still needs to be updated to provide
us with actually random bits.
R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/5599046
Equality on structs will require arbitrary code for type equality,
so change algorithm in type data from uint8 to table pointer.
In the process, trim top-level map structure from
104/80 bytes (64-bit/32-bit) to 24/12.
Equality on structs will require being able to call code generated
by the Go compiler, and C code has no way to access Go return
values, so change the hash and equal algorithm functions to take
a pointer to a result instead of returning the result.
R=ken
CC=golang-dev
https://golang.org/cl/5453043
The old m[x] = 0, false syntax will be deleted
in a month or so, once people have had time to
change their code (there is a gofix in a separate CL).
R=ken2
CC=golang-dev
https://golang.org/cl/5265048
The map implementation was using the C idiom of using
a pointer just past the end of its table as a limit pointer.
Unfortunately, the garbage collector sees that pointer as
pointing at the block adjacent to the map table, pinning
in memory a block that would otherwise be freed.
Fix by making limit pointer point at last valid entry, not
just past it.
Reviewed by Mike Burrows.
R=golang-dev, bradfitz, lvd, r
CC=golang-dev
https://golang.org/cl/5158045
When rnd is called with a second argument of 1, it simply
returns the first argument anyway.
R=golang-dev, r
CC=golang-dev
https://golang.org/cl/4820045
* Reduces malloc counts during gob encoder/decoder test from 6/6 to 3/5.
The current reflect uses Set to mean two subtly different things.
(1) If you have a reflect.Value v, it might just represent
itself (as in v = reflect.NewValue(42)), in which case calling
v.Set only changed v, not any other data in the program.
(2) If you have a reflect Value v derived from a pointer
or a slice (as in x := []int{42}; v = reflect.NewValue(x).Index(0)),
v represents the value held there. Changing x[0] affects the
value returned by v.Int(), and calling v.Set affects x[0].
This was not really by design; it just happened that way.
The motivation for the new reflect implementation was
to remove mallocs. The use case (1) has an implicit malloc
inside it. If you can do:
v := reflect.NewValue(0)
v.Set(42)
i := v.Int() // i = 42
then that implies that v is referring to some underlying
chunk of memory in order to remember the 42; that is,
NewValue must have allocated some memory.
Almost all the time you are using reflect the goal is to
inspect or to change other data, not to manipulate data
stored solely inside a reflect.Value.
This CL removes use case (1), so that an assignable
reflect.Value must always refer to some other piece of data
in the program. Put another way, removing this case would
make
v := reflect.NewValue(0)
v.Set(42)
as illegal as
0 = 42.
It would also make this illegal:
x := 0
v := reflect.NewValue(x)
v.Set(42)
for the same reason. (Note that right now, v.Set(42) "succeeds"
but does not change the value of x.)
If you really wanted to make v refer to x, you'd start with &x
and dereference it:
x := 0
v := reflect.NewValue(&x).Elem() // v = *&x
v.Set(42)
It's pretty rare, except in tests, to want to use NewValue and then
call Set to change the Value itself instead of some other piece of
data in the program. I haven't seen it happen once yet while
making the tree build with this change.
For the same reasons, reflect.Zero (formerly reflect.MakeZero)
would also return an unassignable, unaddressable value.
This invalidates the (awkward) idiom:
pv := ... some Ptr Value we have ...
v := reflect.Zero(pv.Type().Elem())
pv.PointTo(v)
which, when the API changed, turned into:
pv := ... some Ptr Value we have ...
v := reflect.Zero(pv.Type().Elem())
pv.Set(v.Addr())
In both, it is far from clear what the code is trying to do. Now that
it is possible, this CL adds reflect.New(Type) Value that does the
obvious thing (same as Go's new), so this code would be replaced by:
pv := ... some Ptr Value we have ...
pv.Set(reflect.New(pv.Type().Elem()))
The changes just described can be confusing to think about,
but I believe it is because the old API was confusing - it was
conflating two different kinds of Values - and that the new API
by itself is pretty simple: you can only Set (or call Addr on)
a Value if it actually addresses some real piece of data; that is,
only if it is the result of dereferencing a Ptr or indexing a Slice.
If you really want the old behavior, you'd get it by translating:
v := reflect.NewValue(x)
into
v := reflect.New(reflect.Typeof(x)).Elem()
v.Set(reflect.NewValue(x))
Gofix will not be able to help with this, because whether
and how to change the code depends on whether the original
code meant use (1) or use (2), so the developer has to read
and think about the code.
You can see the effect on packages in the tree in
https://golang.org/cl/4423043/.
R=r
CC=golang-dev
https://golang.org/cl/4435042
Prefix all external symbols in runtime by runtime·,
to avoid conflicts with possible symbols of the same
name in linked-in C libraries. The obvious conflicts
are printf, malloc, and free, but hide everything to
avoid future pain.
The symbols left alone are:
** known to cgo **
_cgo_free
_cgo_malloc
libcgo_thread_start
initcgo
ncgocall
** known to linker **
_rt0_$GOARCH
_rt0_$GOARCH_$GOOS
text
etext
data
end
pclntab
epclntab
symtab
esymtab
** known to C compiler **
_divv
_modv
_div64by32
etc (arch specific)
Tested on darwin/386, darwin/amd64, linux/386, linux/amd64.
Built (but not tested) for freebsd/386, freebsd/amd64, linux/arm, windows/386.
R=r, PeterGo
CC=golang-dev
https://golang.org/cl/2899041
because they are in package runtime.
another step to enforcing package boundaries.
R=r
DELTA=732 (114 added, 93 deleted, 525 changed)
OCL=35811
CL=35824