One of the early, incorrect takes I had on Go generics was based on some early boxing benchmarks -- the performance improvement is phenomanal! I thought Generics will benefit any function that takes an empty interface...that's code that uses an marshal/unmarshal pattern!
Except I was wrong. The problem is that at the end of the day, that code is very likely using stdlib or some other library to actually marshal/unmarshal the object/data to/from its wire/object form. And until that code takes T
, boxing will still occur under the covers. And since once the value has been boxed it does not need to be boxed again, if boxing occurs once, the benefit of eliminating it everywhere else above the stack is negated.
To see what I mean, take a look at the encoding/json.Marshal
and Unmarshal
functions in 1.18beta1:
Both functions still take the empty interface (or its type alias, the any
identifier). This means if at any point code that has been painstakingly refactored to use generic types to eliminate boxing calls into one of the above functions -- you've been boxed.
I am not entirely sure these functions can be generic, but unless they are, they impact everything above them.