Go performance: Big Map creation using a literal

722 views
Skip to first unread message

Oleksandr Pryimak

unread,
Nov 28, 2020, 9:54:03 AM11/28/20
to golang-dev
Hello nice people!

While benchmarking one of the functions I noticed that
```
result := make(map[string]float, SIZE) // SIZE >= N
result["key1"] = SOME_COMPUTED_ABOVE_VALUE
result["key2"] = SOME_COMPUTED_ABOVE_VALUE
// more keys here result["keyN"] = SOME_COMPUTED_ABOVE_VALUE
return result
```
works twice as fast then
```
return map[string]float { "key1": SOME_COMPUTED_ABOVE_VALUE, "key2": SOME_COMPUTED_ABOVE_VALUE, // more keys here "keyN": SOME_COMPUTED_ABOVE_VALUE, }
```

cause the latter results in calls to `hashGrows` if N is relatively big (I see this happening when N>=9)

I created small benchmarks to reproduce it.
See here

Do I understand correctly that creating a map using a literal is equivalent to creating an empty map and then filling it?

While one can compute minimal needed capacity to store the map literal I understand that actually allocating the map of this size may result in unexpected behavior (and definitely different from current one). Calculating at compile time what the hash table capacity is not possible cause it depends on env variables controlling that speed of hash tables growth.
At the same time I can imagine that compiler can emit a simple function which would compute the capacity at the runtime and allocate map of proper size.

So my question
1. Are my benchmarks correct?
2. If so is there a reason for this behavior?

Here are benchmarks
Small posts with my bench data

Ian Lance Taylor

unread,
Nov 28, 2020, 2:56:45 PM11/28/20
to Oleksandr Pryimak, golang-dev
It's possible that when compiling map literals the compiler doesn't
make the map with the size of the number of entries in the composite
literal, although it probably should. Want to open an issue at
https://golang.org/issue? Thanks.

Ian

Josh Bleecher Snyder

unread,
Nov 28, 2020, 4:17:59 PM11/28/20
to Ian Lance Taylor, Oleksandr Pryimak, golang-dev
It currently makes a map with the size of the number of statically computable entries. See cmd/compile/internal/gc/sinit.go:757.

It should indeed probably include all entries, even if that means occasionally over-estimating, in the case in which there are duplicate elements. That’ll require a bit of plumbing.

To second Ian: please do file an issue. Thanks!

-josh




Ian

--
You received this message because you are subscribed to the Google Groups "golang-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-dev+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-dev/CAOyqgcX96Ku7RoUdSkeyzWXZx3Q-r3WW078eBVgH%3DEtjFvD6BA%40mail.gmail.com.

Oleksandr Pryimak

unread,
Dec 5, 2020, 1:48:55 AM12/5/20
to Josh Bleecher Snyder, Ian Lance Taylor, golang-dev
Hello Josh and Ian,

I created a ticket
https://github.com/golang/go/issues/43020

Kind regards,
Oleksandr Pryimak

Ian Lance Taylor

unread,
Dec 5, 2020, 11:11:23 AM12/5/20
to Oleksandr Pryimak, Josh Bleecher Snyder, golang-dev
On Fri, Dec 4, 2020 at 10:48 PM Oleksandr Pryimak
<aleksand...@gmail.com> wrote:
>
> I created a ticket
> https://github.com/golang/go/issues/43020

Thanks.

Ian
Reply all
Reply to author
Forward
0 new messages