I don't believe Go is about to get faster, at least not in an especially unique way compared to past releases.<p>Historically the Go compiler has been seeing performance improvements every release, so historically, Go has always been getting faster.<p>When it comes to Generics, the benefits are not so straightforward as simply recompiling with a new binary. I just rebuilt one of our larger services with Go 1.17 and compared it to 1.18 and the benchmarks come out roughly the same after variance. There is a slight improvement, but what's interesting is that we don't use generics anywhere.<p>My employer has a blanket ban on Generics in Go until at least the next release. I know others that do too. There is also nothing in our code base that is screaming to be rewritten with Generics. We collectively thought about it and no one could come up with <i>anything</i> worthwhile. Internally, we're still not sure when they're even warranted. Sure, there's a few three line for-loops that could be removed, but none of those are in a hot path. Yawn.<p>If Go generics radically change the Go ecosystem overnight, they will ruin the language. The ecosystem prefers stability and compatibility over features, and it's pervasive and <i>good</i>. I update Java and JavaScript dependencies regularly and it's a fucking nightmare compared to Go.<p>Lastly, Go had attracted a large community of developers who eschew unnecessary abstractions. It's lovely and refreshing. I can't say the same about Rust or Swift or Scala, where complexity is sometimes celebrated as simplicity when it's really just convenience wearing lipstick.
Not really fair. You could already get this performance, when you cared, by writing the specialized datastructure for the specific types you cared about. So sure, generics let you write type-agnostic libraries that don't pay a boxing/unboxing penalty, but that's not really news!
Deques are great. I think there's two ways I'd consider designing this library differently:<p>1) The resizing seems worse to me than a linked-list of fixed-size ring buffers which use a sync.Pool.
2) (more out there) some of the time when I've implemented this sort of thing, it's been to allocate memory for unmarshaling. It might be nice to have a mechanism to store values and allocate pointers.
<i>"This is encouraging news for a language already known to be unusually both fast and easy"</i><p>Hmm it's not known for that, is it? Go is known to be quite slow due to a weak compiler and a GC that optimizes for latency over throughput. And is Go really easier than a language like Java or in the dynamic world, JavaScript? It sure does seem to have a lot of weird edge cases and potholes to trip over.<p>Anyway I see a bunch of comments saying generics shouldn't make anything faster. They can make code go faster in combination with specialization and value types. It's one of the reasons C++ can go very fast whilst still supporting higher level abstractions, albeit at the cost of generated code size. It's also the reason they're adding value types and specialized generics to the JVM. I don't know if Go is doing C++/Rust style specialization or not, but it at least has the potential to do so.
Something fishy here. A generic data structure is exactly the kind of code that you <i>wouldn’t</i> expect to perform better with generics. At most you’re getting the benefits of unboxing and the absence of a single conditional jump for the type check when you convert back from interface{}. But that shouldn’t make much difference to a series of tests that just push and pop items for a queue. I suspect that any realistic code using this data structure would see no tangible performance benefit. These tests are probably just picking up the cost of an extra allocation required to box a primitive type as an interface.<p>If you’ll excuse the blog spam, I did a dive into the performance of interface{} here: <a href="https://adrummond.net/posts/gogenerics" rel="nofollow">https://adrummond.net/posts/gogenerics</a><p>(The blog post was written before it was certain that Go would get generics.)
All those times in the table seem... Slow...<p>For example, BenchmarkPushFront-10 takes 9 ns... That should consist of one write to memory (to update the pointer in the object). With decent compiler optimizations and a modern out of order CPU, I think we ought to be expecting one of those per clock cycle, so we ought to be seeing performance of 0.5ns. Perhaps even faster if the compiler manages to vectorize stuff (although I'm not aware of any compiler that can vectorize memory allocations).