On Tue, Aug 1, 2017 at 2:43 PM, roger peppe <rogpe...@gmail.com> wrote:
> On 1 August 2017 at 19:33, Josh Humphries <jh...@bluegosling.com> wrote: > > On Tue, Aug 1, 2017 at 11:44 AM, roger peppe <rogpe...@gmail.com> wrote: > >> > >> On 1 August 2017 at 13:57, Josh Humphries <jh...@bluegosling.com> > wrote: > >> > Although that solution creates a heap-allocated tmp for every element > in > >> > the > >> > slice. Using an interface, the value will be inlined instead of > >> > heap-allocated if it fits without boxing (so most primitive types and > >> > pointer types won't need heap allocation). > >> > >> As it happens, it's the other way round - the solution using Interface > can > >> make an allocation per element, but the solution using Value does not. > > > > > > The solution using Value is calling reflect.New inside the loop. Why do > you > > say that it does not make an allocation per element? > > The code I posted doesn't call reflect.New inside the loop - perhaps > you're looking at some different code? (for the record, I'm talking > about line 45 of https://play.golang.org/p/Q0VHbfL7Ij) > Ah, I see. Thanks for the clarification. That makes sense to allocate just one for the whole operation. > > > Also, I'm not sure I follow that using Interface makes an allocation per > > element. My understanding is that the actual value can be stored in the > > interface value if it is small enough (1 or 2 words?). So boxing > primitives > > and pointers should generally store the value in the interface tuple > (which > > itself is stack allocated) as opposed to allocating heap space for it and > > storing a pointer. > > As I think was pointed out earlier in this thread, this has changed since > Go 1. Only pointer values are stored in interface values now - non-pointer > value (for example the ints in the example) will usually cause an > allocation. > There are some optimisations for some cases that avoid that: creation > of an interface from a constant value, and creation of an interface from > small numeric values. > > Ugh. I did not realize that. I had not dug into it too much other than reading a Go blog post and this article by Russ Cox <https://research.swtch.com/interfaces> (which suggest this memory optimization is done). I am guessing the conditional that decides between inline value vs. pointer-chasing was too much runtime overhead? > Try running the benchmark code that I posted. I think you'll find > that the code that calls Interface is slower and allocates more, > because it has to allocate a storage slot every time it creates > an interface from an int, which the solution using Value does not, > because it allocates the temporary only once for a given call to Reverse > (even that could be amortised by using sync.Pool, but it's almost > certainly not worth it). > > cheers, > rog. > -- 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.