-
Notifications
You must be signed in to change notification settings - Fork 18k
runtime: map key hashing is slow for compound types (array/struct) #13271
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
cpu prof for char array test above for example looks like this
|
CC @randall77 |
It does. The speed difference you're seeing is because there is a special-case fast path for maps with int32, int64, or string keys. For maps of size 1 like you're benchmarking, we don't hash at all. That is not the case for [12]byte or [3]int32 keys. We might be able to fix your 1M benchmark. We should still use the fast path if you just wrap an int64 in a struct. I thought we did that already, but maybe not. |
[12]byte and [3]int32 is pretty much string in some sense. It's a byte array with length 12. Is it possible to use fast path in these cases? |
Not in general. Every special case bloats the binary with additional code, and we don't want to special case all of [12]byte, [13]byte, [14]byte, ... |
is it then possible to generalize the fastpath from string-only to ptr+length ? |
No. The fast path is not only about hashing, it also includes fast indexing and copy for the specialized types. A [12]byte and a string with 12 bytes in it do not have the same internal representation. |
Does the fast path work for []byte too? If not, could it? |
Slices may not be map keys. On Mon, 7 Dec 2015, 18:19 Lawrence E. Bakst [email protected]
|
I'm not sure what you are asking. []byte cannot be a map key. It would be fine to be a map value, any values <=128 bytes can be used and still take advantage of the fast path. |
Yep, sorry about that. I didn't remember that slices weren't Key Types. I just came back to delete the comment but it's already too late, you guys are fast. It's too bad though. I have a bunch of hash values I want to store in a map. I guess for now I will cast []byte to string as it's prototype code. I assume that cast has to copy the bytes of the slice to the string so there is an allocation and a copy? Is there any optimization for struct{} as a value take no memory? In my case I just need to test if the hash is in the map and don't care about the value. I have lots of hashes to store in the map. |
That's OK, it took me a few minutes to remember that restriction. I'm so Wrt. var m map[string]T Has an optimisation to avoid the copy for the purposes of hashing. I forget Note: the optimisation is very specific s := string(key) Will incur a copy as expected. Thanks Dave On Mon, 7 Dec 2015, 19:06 Lawrence E. Bakst [email protected]
|
CL https://golang.org/cl/17464 mentions this issue. |
@davecheney thanks for the info on the string cast optimization. |
It seems that map[[8]byte]int is much slower than map[uint64]int purely because of the time spent on hashing the key.
consider this benchmark
my results for this benchmark are as follows
Would love if compiler would recognize that compound types memory layout is flat and hash them as byte arrays.
We currently use workaround like BenchmarkMap1S3U (with map sets constructing real GC visible strings) which is fugly.
tested on go versions 1.4 and 1.5.1
The text was updated successfully, but these errors were encountered: