Francis,

First, fix any bugs.

For example, "The benchmark function must run the target code b.N times." 
https://golang.org/pkg/testing/

Therefore, 

keyVals := make([]string, b.N*10)
// ...
for _, key := range keyVals {
        setOne(s, key)
}

should be

keyVals := make([]string, b.N)
// ...
for _, key := range keyVals {
        setOne(s, key)
}

or

s /b.N*10/b.N/

Then, as expected,

BenchmarkSetOne-4        1000000          2058 ns/op         159 B/op    
       0 allocs/op
BenchmarkSetTwo-4        1000000          4648 ns/op         319 B/op    
       0 allocs/op

Peter

On Friday, September 2, 2016 at 9:07:09 AM UTC-4, Francis wrote:
>
> 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