I think it is kind of intuitive that empty struct takes 0 bytes whereas a
bool variable takes 1 byte in memory and hence a map with struct{} values
would consume lesser memory than the other. I tried checking this using
code and Randall's point proves:
mapmem.go:
package main
import (
"fmt"
_ "net/http/pprof"
"runtime"
"unsafe"
)
const (
entries = 1000001
)
func main() {
printAllocs()
//Empty struct takes 0 bytes in memory whereas a boolean takes 1
s := struct{}{}
b := true
fmt.Printf("size of empty struct: %T, %d\n", s, unsafe.Sizeof(s))
fmt.Printf("size of a boolean: %T, %d\n", b, unsafe.Sizeof(b))
printAllocs()
//Map with int keys and bool values
hashset := make(map[int]bool, entries)
for index := 0; index < entries-1; index++ {
hashset[index] = true
}
fmt.Printf("Number of elements in map with bool values: %d \n", len(
hashset))
printAllocs()
//Map with int keys and empty struct values
hashmap := make(map[int]struct{}, entries)
for index := 0; index < entries-1; index++ {
hashmap[index] = struct{}{}
}
fmt.Printf("Number of elements in map with empty struct values: %d \n",
len(hashmap))
printAllocs()
}
func printAllocs() {
var m runtime.MemStats
runtime.ReadMemStats(&m)
fmt.Printf("Heap size: %6d \n", m.Alloc/1e6)
}
And here is the output: (Please note that the GC runs and collects memory
in between most of the times and hence the total heap size shows 22MB
rather than 47MB)
$ GODEBUG=gctrace=1 ./mapmem
Heap size: 0
size of empty struct: struct {}, 0
size of a boolean: bool, 1
Heap size: 0
gc 1 @0.002s 1%: 0.002+0.25+0.019 ms clock, 0.009+0.11/0.045/0.37+0.079 ms
cpu, 23->23->23 MB, 24 MB goal, 4 P
Number of elements in map with bool values: 1000000
Heap size: 24
gc 2 @0.129s 0%: 0.003+0.25+0.018 ms clock, 0.012+0.076/0.066/0.22+0.072 ms
cpu, 44->44->21 MB, 47 MB goal, 4 P
Number of elements in map with empty struct values: 1000000
Heap size: 22
As you can see, the map with struct{} values grows the heap size to ~22 MB,
whereas the map with bool values takes it close to ~24 MB for a million
entries. Hence, if you are concerned about memory usage, you would rather
use empty struct values.
I still feel a map with bool values is easier to read though, but that's
just my opinion. :)
On Wednesday, 29 April 2020 00:18:12 UTC+5:30, [email protected] wrote:
>
>
> is it mentioned anywhere such that "map[string]struct{}" is efficeient?
>
> On Tuesday, April 28, 2020 at 10:23:08 AM UTC+5:30, Randall O'Reilly wrote:
>>
>> I think map[string]struct{} takes no storage for the value and is the
>> most efficient way to do this.
>>
>> - Randy
>>
>> > On Apr 27, 2020, at 7:20 PM, Shishir Verma <[email protected]> wrote:
>> >
>> > I think the idiomatic way to implement a set in golang is to use a map
>> with bool values. Here is an example from effective go documentation:
>> >
>> >
>> > attended := map[string]bool{
>> > "Ann": true,
>> > "Joe": true,
>> > ...
>> > }
>> >
>> > if attended[person] { // will be false if person is not in the map
>> > fmt.Println(person, "was at the meeting")
>> > }
>> >
>> >
>> >
>> > On Monday, 27 April 2020 22:16:20 UTC+5:30, [email protected]
>> wrote:
>> > Basically i need a slice with indexed values, so that i can check only
>> existence.
>> > or a map with only keys?
>> > How it can be done?
>> >
>> > --
>> > You received this message because you are subscribed to the Google
>> Groups "golang-nuts" group.
>> > To unsubscribe from this group and stop receiving emails from it, send
>> an email to [email protected].
>> > To view this discussion on the web visit
>> https://groups.google.com/d/msgid/golang-nuts/1201e6f3-621e-4875-9374-d7713fa7d8aa%40googlegroups.com.
>>
>>
>>
>>
--
You received this message because you are subscribed to the Google Groups
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/golang-nuts/afa734a9-edab-4358-aed9-de4a80a1c3a5%40googlegroups.com.