Just an FYI - this is by no means Go related. These problems and techniques are 
very common when doing HPC micro benchmarking. 

> On Mar 24, 2020, at 4:10 PM, Orson Cart <objectivedynam...@gmail.com> wrote:
> 
> 
>> On Tuesday, 24 March 2020 21:00:38 UTC, Sean Liao wrote:
>> setup upfront shouldn't be a problem
>> b.N is constant throughout the function lifetime, the entire function is 
>> called multiple times during benchmarking
> 
> Thank you! I'd missed that. That makes things so much more straightforward 
> for me.
> 
>  
>> 
>>> On Tuesday, March 24, 2020 at 9:56:19 PM UTC+1, Orson Cart wrote:
>>>> On Tuesday, 24 March 2020 20:47:07 UTC, Robert Engels wrote:
>>>> One way to handle this is to generate all of the data up front in an array 
>>>> and then just index into the array based on the run. 
>>> 
>>> Yeah, I had thought of that before posting but then I'd have to decide on a 
>>> value for b.N. I was trying to roll with the idea of the framework 
>>> establishing a value. To be honest if it wasn't for the fact that I was 
>>> just curious as to why it wasn't working I'd just have settled for an array 
>>> with a fixed b.N.
>>> 
>>> All part of my golang learning experience
>>> 
>>>  
>>>> 
>>>>>> On Mar 24, 2020, at 3:42 PM, Orson Cart <objectiv...@gmail.com> wrote:
>>>>>> 
>>>>> 
>>>>> 
>>>>> 
>>>>>> On Tuesday, 24 March 2020 20:27:39 UTC, Adrian Ratnapala wrote:
>>>>>> ...
>>>>>> So that sounds like the use-case is to call Stop-, StartTimer once 
>>>>>> before you enter the main loop of the benchmark.  They not efficient 
>>>>>> enough for a tight inner loop. 
>>>>> 
>>>>> Thanks for the input and I think that you are probably correct. It would 
>>>>> be nice if the docs said that though.
>>>>> 
>>>>> The code that I'm profiling wasn't written by me. It's fast but it 
>>>>> modifies its input data so it needs new data on each iteration. The 
>>>>> implementation is non-trivial and it might be a maintenance headache. 
>>>>> I've been asked to benchmark it along with less complicated 
>>>>> implementations. It was whilst trying to set up per-iteration test data 
>>>>> that I came across this issue.
>>>>> 
>>>>> 
>>>>> 
>>>>> 
>>>>> 
>>>>> 
>>>>> 
>>>>>  
>>>>>> 
>>>>>> On Wed, 25 Mar 2020 at 06:51, Jake Montgomery <jake...@gmail.com> wrote: 
>>>>>> > 
>>>>>> > Strange. I hope someone has a real answer for you. 
>>>>>> > 
>>>>>> > In the meantime, you can simplify your example to demonstrate the 
>>>>>> > issue: 
>>>>>> > 
>>>>>> > package demo_test 
>>>>>> > 
>>>>>> > import ( 
>>>>>> >     "testing" 
>>>>>> > ) 
>>>>>> > 
>>>>>> > var Foo1 []string 
>>>>>> > var Count int = 8 
>>>>>> > 
>>>>>> > func Benchmark1(b *testing.B) { 
>>>>>> >     for i := 0; i < b.N; i++ { 
>>>>>> >         Foo1 = foo(Count) 
>>>>>> >     } 
>>>>>> > } 
>>>>>> > 
>>>>>> > func Benchmark2(b *testing.B) { 
>>>>>> >     b.StopTimer() 
>>>>>> >     for i := 0; i < b.N; i++ { 
>>>>>> >         // Hypothetical setup here 
>>>>>> >         b.StartTimer() 
>>>>>> >         Foo1 = foo(Count) 
>>>>>> >         b.StopTimer() 
>>>>>> >     } 
>>>>>> > } 
>>>>>> > 
>>>>>> > 
>>>>>> > func foo(count int) []string { 
>>>>>> >     testData := []string{} 
>>>>>> >     for i := 0; i < count; i++ { 
>>>>>> >         testData = append(testData, "a") 
>>>>>> >     } 
>>>>>> > 
>>>>>> >     return testData 
>>>>>> > } 
>>>>>> > 
>>>>>> > I get: 
>>>>>> > 
>>>>>> > goos: windows 
>>>>>> > goarch: amd64 
>>>>>> > Benchmark1-4     2101567               584 ns/op 
>>>>>> > Benchmark2-4     1000000              1668 ns/op 
>>>>>> > PASS 
>>>>>> > 
>>>>>> > So it appears that StopTimer() and StartTimer() are introducing some 
>>>>>> > overhead. I am surprised that it is this large. 
>>>>>> > 
>>>>>> > Good Luck 
>>>>>> > 
>>>>>> > 
>>>>>> > 
>>>>>> > On Tuesday, March 24, 2020 at 12:24:08 PM UTC-4, Orson Cart wrote: 
>>>>>> >> 
>>>>>> >> I posted this earlier but I realised that the code had a fundamental 
>>>>>> >> error in it. I've corrected here it but the underlying problem still 
>>>>>> >> exists. 
>>>>>> >> 
>>>>>> >> I've recently started using go test's benchmarks support and I'm 
>>>>>> >> particularly interested in understanding the benchmark timer 
>>>>>> >> functions. I've been getting results that I found surprising and I 
>>>>>> >> was wondering if anyone could explain what's going on here. 
>>>>>> >> 
>>>>>> >> The code below has three benchmarks that each invoke a single 
>>>>>> >> function (foo). The implementation of foo isn't important, it's just 
>>>>>> >> there to consume some time:
>>>>>> >> - foo is called once per iteration in Benchmark1. 
>>>>>> >> - It's called twice per iteration in Benchmark2 so I'd expect 
>>>>>> >> Benchmark2's duration to be nominally twice that of Benchmark1. 
>>>>>> >> - It's also called twice per iteration in Benchmark3 but the first 
>>>>>> >> call is wrapped in b.StopTimer and b.startTimer calls. Because of 
>>>>>> >> this I'd have expected Benchmark3 to be about the same duration as 
>>>>>> >> Benchmark1 
>>>>>> >> 
>>>>>> >> Apologies for the length of the example but I didn't think it fair to 
>>>>>> >> ask the question and leave anything out. 
>>>>>> >> 
>>>>>> >> package demo_test 
>>>>>> >> 
>>>>>> >> import ( 
>>>>>> >> "strconv" 
>>>>>> >> "testing" 
>>>>>> >> ) 
>>>>>> >> 
>>>>>> >> var Foo1 []string 
>>>>>> >> var Foo2 []string 
>>>>>> >> var Count int = 32767 
>>>>>> >> 
>>>>>> >> func Benchmark1(b *testing.B) { 
>>>>>> >> for i := 0; i < b.N; i++{ 
>>>>>> >> Foo1 = foo(Count) 
>>>>>> >> } 
>>>>>> >> } 
>>>>>> >> 
>>>>>> >> func Benchmark2(b *testing.B) { 
>>>>>> >> for i := 0; i < b.N; i++{ 
>>>>>> >> Foo1 = foo(Count) 
>>>>>> >> Foo2 = foo(Count) 
>>>>>> >> } 
>>>>>> >> } 
>>>>>> >> 
>>>>>> >> func Benchmark3(b *testing.B) { 
>>>>>> >> for i := 0; i < b.N; i++{ 
>>>>>> >> b.StopTimer() 
>>>>>> >> Foo1 = foo(Count) 
>>>>>> >> b.StartTimer() 
>>>>>> >> Foo2 = foo(Count) 
>>>>>> >> } 
>>>>>> >> } 
>>>>>> >> 
>>>>>> >> func foo(count int) []string{ 
>>>>>> >> testData := []string{} 
>>>>>> >> for i:= 0; i < count; i++ { 
>>>>>> >> testData = append(testData, strconv.Itoa(i)) 
>>>>>> >> } 
>>>>>> >> 
>>>>>> >> return testData 
>>>>>> >> } 
>>>>>> >> 
>>>>>> >> 
>>>>>> >> When the benchmarks are run the results are as follows: 
>>>>>> >> 
>>>>>> >> Benchmark1-4         351           3345215 ns/op 
>>>>>> >> Benchmark2-4         166           7206582 ns/op 
>>>>>> >> Benchmark3-4         334           3457907 ns/op 
>>>>>> >> PASS 
>>>>>> >> ok      bar.com/benchmarks      6.881s 
>>>>>> >> 
>>>>>> >> OK benchmark3 is a little slower than Benchmark1 but that's not 
>>>>>> >> what's bothering me. It's this: if I now change Count to something 
>>>>>> >> much smaller the results are a surprise, at least to me. Here are the 
>>>>>> >> results when Count = 8: 
>>>>>> >> 
>>>>>> >> Benchmark1-4     2706196               442 ns/op 
>>>>>> >> Benchmark2-4     1357482               873 ns/op 
>>>>>> >> Benchmark3-4      840729              1387 ns/op 
>>>>>> >> PASS 
>>>>>> >> ok      bar.com/benchmarks      23.547s 
>>>>>> >> 
>>>>>> >> The ratio of timings for Benchmark1 and Benchmark2 are roughly in 
>>>>>> >> line with expectations but I was surprised to see that the timings 
>>>>>> >> for Benchmark3 are now larger than those for Benchmark2. 
>>>>>> >> 
>>>>>> >> Can anyone explain this? 
>>>>>> >> 
>>>>>> >> TIA 
>>>>>> >> Orson 
>>>>>> > 
>>>>>> > -- 
>>>>>> > 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 golan...@googlegroups.com. 
>>>>>> > To view this discussion on the web visit 
>>>>>> > https://groups.google.com/d/msgid/golang-nuts/feda7e38-5d1f-43cf-b0cd-98db0a94d3c9%40googlegroups.com.
>>>>>> >  
>>>>>> 
>>>>>> 
>>>>>> 
>>>>>> -- 
>>>>>> Adrian Ratnapala 
>>>>> 
>>>>> -- 
>>>>> 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 golan...@googlegroups.com.
>>>>> To view this discussion on the web visit 
>>>>> https://groups.google.com/d/msgid/golang-nuts/291af5de-8a01-4c30-98bb-d4765e3a5333%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 golang-nuts+unsubscr...@googlegroups.com.
> To view this discussion on the web visit 
> https://groups.google.com/d/msgid/golang-nuts/8cf5eec8-9cb9-47ed-b444-e8a689d403ff%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 golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/5BE42686-4DDA-46E1-8555-950C6162783F%40ix.netcom.com.

Reply via email to