Hi Paul,

Check out: https://golang.org/doc/effective_go.html#pointers_vs_values

Basically, in your index1, the opts.isDigit passed to IndexFunc is 
syntactic sugar for (&opts).isDigit -> then the compiler needs to move opts 
on the heap. 

You can either 
a) define an alternate isDigitVal method, e.g. func (opts options) 
isDigitMethodByVal(r rune) bool
or 
b) you can just pass the reference to an original *options from the get go:

func index1Pointer(s string, optsPointer *options) int {
return strings.IndexFunc(s, optsPointer.isDigit)
}

Not sure which one will be faster - you'll need to benchmark. Probably both 
will be about the same, since that single *options allocation tends to zero.

For your index2 function question, I think it's because Go maintains the 
variables from a parent function that are referred in an enclosed function 
(closure) for as long as both are alive. 
I'm guessing that opts.IsDigit(r) is alive and kicking till it returns. 

cheers,
silviu

On Tuesday, 4 September 2018 17:46:09 UTC-4, Paul D wrote:
>
> I'm trying to reduce allocations (and improve performance) in some Go 
> code. There's a recurring pattern in the code where a struct is passed to a 
> function, and the function passes one of the struct's methods to 
> strings.IndexFunc. For some reason, this causes the entire struct to escape 
> to the heap. If I wrap the method call in an anonymous function, the struct 
> does not escape and the benchmarks run about 30% faster.
>
> Here is a minimal example. In the actual code, the struct has more 
> fields/methods and the function in question actually does something. But 
> this sample code illustrates the problem. Why does the opts argument escape 
> to the heap in index1 but not in the functionally equivalent index2? And is 
> there a robust way to ensure that it stays on the stack?
>
>
> type options struct {
>     zero rune
> }
>
> func (opts *options) isDigit(r rune) bool {
>     r -= opts.zero
>     return r >= 0 && r <= 9
> }
>
> // opts escapes to heap
> func index1(s string, opts options) int {
>     return strings.IndexFunc(s, opts.isDigit)
> }
>
> // opts does not escape to heap
> func index2(s string, opts options) int {
>     return strings.IndexFunc(s, func(r rune) bool {
>         return opts.isDigit(r)
>     })
> }
>
>
> FYI I'm running Go 1.10.3 on Linux. Thanks...
>
>
>

-- 
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