@Arnaud: I tend to agree that it's a downside of having two ways to do
things. However, I don't know how we would get the actually additive
expressive power of generics without that downside. If you have any ideas,
that would be great.

@Robert: I think sweeping statements about the performance of generic code
vs. non-generic code are premature. In particular, in a situation where
*either* generics *or* interfaces can be used for the same effect, I think
the goal should be for both to perform equivalently. In those cases, there
is nothing preventing the compiler from doing exactly the same
optimizations - that is, nothing in the language prescribing that an
interface needs to be passed and used as a boxed value, instead of
devirtualizing the function to operate on each concrete type it is called
with. In fact, AIUI, go 1.16 will already be significantly more clever
about doing that optimization.
Of course there *are* cases where it's not possible to devirtualize a
function. But in those cases, generics will run into similar problems.

I think it remains to be seen, if and when there is a performance benefit
and how large it is. Personally, *because* I would prefer us to continue to
favor interface-code where it can be used and only reach for generics if
they are necessary, I would very much like them to perform similarly, so
people don't use generics just "because they're faster".

On Sun, Dec 27, 2020 at 6:54 PM K. Alex Mills <k.alex.mi...@gmail.com>
wrote:

> Makes sense. I just attempted to quantify the overhead and it looks like
> it's at least 2x on my machine, which is not as trivial a performance bump
> as I had imagined, so thanks for the push back.
>
> There are clearly some uses for which this pattern is going to be
> desirable for the performance benefits of monomorphization.
>
> Benchmark I used is included below, for completeness. It only quantifies
> the overhead of interface dispatch, which I think is the salient point. It
> may be worth noting that I don't have a go2 compiler locally and the
> playground doesn't support benchmarks. OTOH, this performance may be closer
> to what we might expect from go2 in case the current prototype isn't (yet)
> as optimized as it could be.
>
> package main
>
> import (
>   "strconv"
>   "testing"
> )
>
> func BenchmarkNonGenericScalar(b *testing.B) {
>   x := myInt(5341)
>   for i := 0; i < b.N; i++ {
>     nonGeneric(x)
>   }
> }
>
> func BenchmarkGenericScalar(b *testing.B) {
>   x := myInt(5341)
>   for i := 0; i < b.N; i++ {
>     generic(x)
>   }
> }
>
> type Stringer interface {
>   String() string
> }
>
> func nonGeneric(x Stringer) string {
>   return x.String()
> }
>
> // my assumption here is this will output monomorphized binary code
> roughly equivalent to
> // what the generics implementation would output; that assumption may be
> wrong.
> func generic(x myInt) string {
>   return x.String()
> }
>
> type myInt int
>
> func (i myInt) String() string {
>   return strconv.Itoa(int(i))
> }
>
> BenchmarkNonGenericScalar
> BenchmarkNonGenericScalar-24
> 21053407          55.3 ns/op        16 B/op        2 allocs/op
> BenchmarkGenericScalar
> BenchmarkGenericScalar-24
> 52173685          23.7 ns/op         4 B/op        1 allocs/op
> PASS
>
> On Sun, Dec 27, 2020 at 11:35 AM robert engels <reng...@ix.netcom.com>
> wrote:
>
>> That is not true. The generic version can have significant performance
>> implications for low-level/tight-loop functions as it will avoid the
>> indirection required for interface method dispatching (at the expensive of
>> code explosion for common calls with lots of types).
>>
>> On Dec 27, 2020, at 11:31 AM, K. Alex Mills <k.alex.mi...@gmail.com>
>> wrote:
>>
>> Since in this case the use of generics doesn't let you do anything new, I
>> would argue that the KISS principle applies and the non-generic version
>> should be preferred.
>>
>> I think a linter can be added to go vet to warn about instances like this
>> one (where the type parameter can be replaced by the type bound) to
>> encourage simplicity.
>>
>> But as Ian pointed out, in the version that takes a slice argument, using
>> generics does allow you to do something you couldn't do otherwise (without
>> reallocating the contents of the slice to effect a "cast" to []Stringer).
>> In this case using generics actually makes the caller's job simpler and
>> improves performance by avoiding the need for reallocation.
>>
>> On Sun, Dec 27, 2020 at 4:23 AM Arnaud Delobelle <arno...@gmail.com>
>> wrote:
>>
>>> In my opinion, the issue is that there are two ways to express (almost)
>>> the same thing and that in itself creates friction in the language.
>>>
>>> There may be a valid reason to choose one version over the other, but
>>> every time it will be necessary to review the pros and cons of each
>>> alternative.
>>>
>>> If we could have "generics" without having to make this choice it would
>>> unblock the whole thing as far as I am concerned.
>>>
>>> Cheers
>>>
>>> On Sun, 27 Dec 2020, 05:25 K. Alex Mills, <k.alex.mi...@gmail.com>
>>> wrote:
>>>
>>>> While it depends on the final generics implementation, my understanding
>>>> of how things stand now is that Print would compile down to a separate
>>>> chunk of binary for each type T that is used. For instance, if you used
>>>> Print[A] and Print[B] in your code, they would each refer to separate
>>>> binary implementations in which T is replaced by A and B, respectively.
>>>>
>>>> Printi does not do this, so you should see a smaller binary.
>>>>
>>>> IIRC, Printi also has to do a bit of work to lookup the Stringer method
>>>> on the type inhabiting the interface. I don't think that creates a
>>>> significant performance hit, but I might be understating the overhead of
>>>> interface dispatch. A benchmark would help here (alas, I am on my phone).
>>>>
>>>> With respect for the concerns mentioned above, I don't see an argument
>>>> for preferring Print over Printi. However, there may other concerns which I
>>>> am unaware of.
>>>>
>>>> On Sat, Dec 26, 2020, 9:58 PM Elliot <z11i...@gmail.com> wrote:
>>>>
>>>>> If we remove slice from OP's example:
>>>>>
>>>>> https://go2goplay.golang.org/p/KSJpRw1Lrmm
>>>>>
>>>>> func Print[T Stringer](s T) {
>>>>>     fmt.Print(s.String())
>>>>> }
>>>>>
>>>>> func Printi(s Stringer) {
>>>>>     fmt.Print(s.String())
>>>>> }
>>>>>
>>>>> Are these two equivalent? When should one be chosen over the other?
>>>>>
>>>>> On Thursday, 24 December 2020 at 04:41:16 UTC+8 Henrik Johansson wrote:
>>>>>
>>>>>> Why will interfaces be more idiomatic once generics lands? It remains
>>>>>> to be seen I guess but I could very well see the other way become the 
>>>>>> idiom.
>>>>>>
>>>>>> On Wed, 23 Dec 2020, 21:20 wilk, <w...@flibuste.net> wrote:
>>>>>>
>>>>>>> On 23-12-2020, Ian Lance Taylor wrote:
>>>>>>> > On Wed, Dec 23, 2020 at 9:54 AM wilk <w...@flibuste.net> wrote:
>>>>>>> >>
>>>>>>> >> https://go2goplay.golang.org/p/fTW3hJYNgfU
>>>>>>> >>
>>>>>>> >> type Stringer interface {
>>>>>>> >>    String() string
>>>>>>> >> }
>>>>>>> >>
>>>>>>> >> Print[T Stringer](s []T)
>>>>>>> >>
>>>>>>> >> Print(s []Stringer)
>>>>>>> >>
>>>>>>> >> Both forms works.
>>>>>>> >> How to prevent double way to do the same things that can be
>>>>>>> confusing ?
>>>>>>> >
>>>>>>> > Both forms work but they mean two different things.
>>>>>>> >
>>>>>>> > Print(s []Stringer) takes a slice of the type Stringer.
>>>>>>> >
>>>>>>> > Print[T Stringer](s []T) takes a slice of some type T, where T
>>>>>>> > implements Stringer.
>>>>>>> >
>>>>>>> > For example, if MyInt implements Stringer, and I have a []MyInt,
>>>>>>> then
>>>>>>> > I can call Print[T Stringer](s []T) but I can't call Print(s
>>>>>>> > []Stringer), because a []Stringer is not a []MyInt.
>>>>>>>
>>>>>>> I understand the differences. But i'm affraid someone who never used
>>>>>>> Go before will use type parameters instead of interface which is more
>>>>>>> idiomatic i think.
>>>>>>> I mean it will be difficult to say, you could use type parameters but
>>>>>>> you should use interface, or something like that...
>>>>>>> I'm speaking about ease of learn Go2.
>>>>>>>
>>>>>>> --
>>>>>>> wilk
>>>>>>>
>>>>>>> --
>>>>>>> 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/rs08pp%24p8m%241%40ciao.gmane.io
>>>>>>> .
>>>>>>>
>>>>>>
>>>>> --
>>>>> 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/d044ae30-7254-4a86-9cba-1bc18eeb7fefn%40googlegroups.com
>>>>> <https://groups.google.com/d/msgid/golang-nuts/d044ae30-7254-4a86-9cba-1bc18eeb7fefn%40googlegroups.com?utm_medium=email&utm_source=footer>
>>>>>
>>>>
>>>> --
>>>> 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/CALJzkY-asEOYK1_zgVzNJ4B37u17QX0hZr5vZGADe-vEJgTtQA%40mail.gmail.com
>>>> <https://groups.google.com/d/msgid/golang-nuts/CALJzkY-asEOYK1_zgVzNJ4B37u17QX0hZr5vZGADe-vEJgTtQA%40mail.gmail.com?utm_medium=email&utm_source=footer>
>>>> .
>>>>
>>>
>> --
>> 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/CALJzkY9y%3DRyJ_C4Hm1tvHABcex%2B8o89ydBxL_NXrt2ubtLauLw%40mail.gmail.com
>> <https://groups.google.com/d/msgid/golang-nuts/CALJzkY9y%3DRyJ_C4Hm1tvHABcex%2B8o89ydBxL_NXrt2ubtLauLw%40mail.gmail.com?utm_medium=email&utm_source=footer>
>> .
>>
>>
>> --
> 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/CALJzkY936wTsdBGU7Liasds7-SEXhqy_Y4WLUYg8vhyQfHw_XA%40mail.gmail.com
> <https://groups.google.com/d/msgid/golang-nuts/CALJzkY936wTsdBGU7Liasds7-SEXhqy_Y4WLUYg8vhyQfHw_XA%40mail.gmail.com?utm_medium=email&utm_source=footer>
> .
>

-- 
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/CAEkBMfEcCxjg%3DFGgw3BsiubWO7iL8O-22PbrejXR4LO9cKfDhA%40mail.gmail.com.

Reply via email to