I have been working to reduce allocations in a local cache and found some 
confusing behaviour around the allocs/op output when benchmarking.

A simplified reproducing version is pasted at bottom.

The behaviour is that setting a value in a single map yields 0 allocations, 
setting a value in two maps inside the same function yields 1 allocation. 
Increasing the number of times the Set*() method is called in the benchmark 
(below I am using b.N*10) doesn't change the number of allocations.

Trying to track down this I have used GOSSAFUNC to inspect both setOne(...) 
and setTwo(...). I couldn't identify any allocations, although I am not 
confident in my reading of the SSA output.

I also ran 'go test -bench=.* -memprofile mem.out' which showed 0 
allocations.

So I am confused and wanted to ask for clarification on these measurements. 
It is interesting to me that the setTwo(...) function allocates where the 
setOne(...) does not, but also that the allocations to the underlying maps 
don't appear to be recorded by any of the tools I have used here.


package test


type server struct {
        first  map[string]string
        second map[string]string
}


func new() *server {
        return &server{
                first:  make(map[string]string),
                second: make(map[string]string),
        }
}


func setOne(s *server, key string) {
        s.first[key] = key
}


func setTwo(s *server, key string) {
        s.first[key] = key
        s.second[key] = key
}

with corresponding benchmark



package test


import (
    "strconv"
    "testing"
)


func BenchmarkSetOne(b *testing.B) {
    keyVals := make([]string, b.N*10)
    for i := range keyVals {
            keyVals[i] = strconv.Itoa(i)
    }
    s := &server{
            first:  make(map[string]string),
            second: make(map[string]string),
    }
    b.ResetTimer()
    b.ReportAllocs()
    for _, key := range keyVals {
            setOne(s, key)
    }
}


func BenchmarkSetTwo(b *testing.B) {
    keyVals := make([]string, b.N*10)
    for i := range keyVals {
            keyVals[i] = strconv.Itoa(i)
    }
    s := &server{
            first:  make(map[string]string),
            second: make(map[string]string),
    }
    b.ResetTimer()
    b.ReportAllocs()
    for _, key := range keyVals {
            setTwo(s, key)
    }
}

-- 
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 golang-nuts+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to