TE
科技回声
首页24小时热榜最新最佳问答展示工作
GitHubTwitter
首页

科技回声

基于 Next.js 构建的科技新闻平台,提供全球科技新闻和讨论内容。

GitHubTwitter

首页

首页最新最佳问答展示工作

资源链接

HackerNews API原版 HackerNewsNext.js

© 2025 科技回声. 版权所有。

Generics can make your Go code slower

449 点作者 tanoku大约 3 年前

32 条评论

nvarsj大约 3 年前
I&#x27;d argue that golang is inherently not a systems language, with its mandatory GC managed memory. I think it&#x27;s a poor choice for anything performance or memory sensitive, especially a database. I know people would disagree (hence all the DBs written in golang these days, and Java before it), but I think C&#x2F;C++&#x2F;Rust&#x2F;D are all superior for that kind of application.<p>All of which is to say, I don&#x27;t think it matters. Use the right tool for the job - if you care about generic overhead, golang is not the right thing to use in the first place.
评论 #30858491 未加载
评论 #30858695 未加载
评论 #30858814 未加载
评论 #30858565 未加载
评论 #30858408 未加载
评论 #30860755 未加载
评论 #30858981 未加载
评论 #30861803 未加载
评论 #30861207 未加载
评论 #30859592 未加载
评论 #30862541 未加载
评论 #30858541 未加载
评论 #30864370 未加载
评论 #30861243 未加载
评论 #30860371 未加载
评论 #30860520 未加载
评论 #30862966 未加载
评论 #30862135 未加载
评论 #30860776 未加载
评论 #30864351 未加载
评论 #30858480 未加载
评论 #30859291 未加载
评论 #30868716 未加载
评论 #30869654 未加载
评论 #30860848 未加载
评论 #30859458 未加载
评论 #30858562 未加载
komuW大约 3 年前
Go does has some form of monomorphization implemented in Go1.18; it is just behind a feature flag(compiler flags).<p>Look at the assembly difference between this two examples:<p>1. <a href="https:&#x2F;&#x2F;godbolt.org&#x2F;z&#x2F;7r84jd7Ya" rel="nofollow">https:&#x2F;&#x2F;godbolt.org&#x2F;z&#x2F;7r84jd7Ya</a> (without monomorphization)<p>2. <a href="https:&#x2F;&#x2F;godbolt.org&#x2F;z&#x2F;5Ecr133dz" rel="nofollow">https:&#x2F;&#x2F;godbolt.org&#x2F;z&#x2F;5Ecr133dz</a> (with monomorphization)<p>If you don&#x27;t want to use godbolt, run the command `go tool compile &#x27;-d=unified=1&#x27; -p . -S main.go`<p>I guess that the flag is not documented because the Go team has not committed themselves to whichever implementation.
评论 #30860165 未加载
评论 #30870965 未加载
trey-jones大约 3 年前
This is a really long and informative article, but I would propose a change to the title here, since &quot;Generics can make your Go code slower&quot; seems like the expected outcome, where the conclusion of the article leans more towards &quot;Generics don&#x27;t always make your code slower&quot;, as well as enumerating some good ways to use generics, as well as some anti-patterns.
评论 #30858372 未加载
评论 #30858351 未加载
评论 #30858119 未加载
评论 #30857264 未加载
zachruss92大约 3 年前
For me Go has replaced Node as my preferred backend language. The reason is because of the power of static binaries, the confidence that the code I write today can still run ten years from now, and the performance.<p>The difference in the code I’m working with is being able to handle 250 req&#x2F;s in node versus 50,000 req&#x2F;s in Go without me doing any performance optimizations.<p>From my understanding Go was written with developer ergonomics first and performance is a lower priority. Generics undoubtedly make it a lot easier to write and maintain complex code. That may come at a performance cost but for the work I do even if it cuts the req&#x2F;s in half I can always throw more servers at the problem.<p>Now if I was writing a database or something where performance is paramount I can understand where this can be a concern, it just isn’t for me.<p>I’d be very curious what orgs like CockroachDB and even K8s think about generics at the scale they’re using them.
评论 #30863152 未加载
评论 #30860615 未加载
评论 #30860053 未加载
评论 #30860031 未加载
socialdemocrat大约 3 年前
Really well written article. I liked that the author tried to keep a simple language around a fair amount of complex topics.<p>Although the article paints the Go solution for generics somewhat negative, it actually made me more positive to the Go solution.<p>I don&#x27;t want generic code to be pushed everywhere in Go. I like Go to stay simple and it seems the choices the Go authors have made will discourage overuse of Generics. With interfaces you already avoid code duplication so why push generics? It is just a complication.<p>Now you can keep generics to the areas were Go didn&#x27;t use to work so great.<p>Personally I quite like that Go is trying to find a niche somewhere between languages such as Python and C&#x2F;C++. You get better performance than Python, but they are not seeking zero-overhead at any cost like C++ which dramatically increases complexity.<p>Given the huge amount of projects implemented with Java, C#, Python, Node etc there must be more than enough cases where Go has perfectly good performance. In the more extreme cases I suspect C++ and Rust are the better options.<p>Or if you do number crunching and more scientific stuff then Julia will actually outperform Go, despite being dynamically typed. Julia is a bit opposite of Go. Julia has generics (parameterized types) for performance rather than type safety.<p>In Julia you can create functions taking interface types and still get inlining and max performance. Just throwing it out there are many people seem to think that to achieve max performance you always need a complex statically typed language like C++&#x2F;D&#x2F;Rust. No you don&#x27;t. There are also very high speed dynamic languages (well only Julia I guess at the moment. Possibly LuaJIT and Terra).
评论 #30863157 未加载
klodolph大约 3 年前
I&#x27;m excited about generics that gives you a tradeoff between monomorphization and &quot;everything is a pointer&quot;. The &quot;everything is a pointer&quot; approach, like Haskell, is incredibly inefficient wrt execution time and memory usage, the &quot;monomorphize everything&quot; approach can explode your code size surprisingly fast.<p>I wouldn&#x27;t be surprised if we get some control over monomorphization down the line, but if Go started with the monomorphization approach, it would be impossible to back out of it because it would cause performance regressions. Starting with the shape stenciling approach means that introducing monomorphization later can give you a performance improvement.<p>I&#x27;m not trying to predict whether we&#x27;ll get monomorphization at some future point in Go, but I&#x27;m just saying that at least the door is open.
评论 #30858377 未加载
评论 #30858291 未加载
评论 #30858164 未加载
评论 #30858198 未加载
评论 #30858423 未加载
pphysch大约 3 年前
My first use of Go generics has been for a concurrent &quot;ECS&quot; game engine. In this case, the gains are pretty obvious. I think.<p>I get to write one set of generic methods and data structures that operate over arbitrary &quot;Component&quot; structs, and I can allocate all my components of a particular type contiguously on the heap, then iterate over them with arbitrary, type-safe functions.<p>I can&#x27;t fathom that doing this via a Component interface would be even as close as fast, because it would destroy cache performance by introducing a bunch of Interface tuples and pointer dereferencing for every single instance. Not to mention the type-unsafe code being yucky. Am I wrong?<p>FWIW I was able to update 2,000,000 components per (1&#x2F;60s) frame per thread in a simple Game of Life prototype, which I am quite happy with. But I never bothered to evaluate if Interfaces would be as fast
评论 #30858785 未加载
评论 #30860297 未加载
评论 #30858006 未加载
brundolf大约 3 年前
This is super interesting and well-written. Also, wow, that generated-assembly-viewer widget is slick.
评论 #30860118 未加载
cube2222大约 3 年前
Great article, just skimmed it, but will definitely dive deeper into it. I thought Go is doing full monomorphization.<p>As another datapoint I can add that I tried to replace the interface{}-based btree that I use as the main workhorse for grouping in OctoSQL[0] with a generic one, and got around 5% of a speedup out of it in terms of records per second.<p>That said, compiling with Go 1.18 vs Go 1.17 got me a 10-15% speedup by itself.<p>[0]:<a href="https:&#x2F;&#x2F;github.com&#x2F;cube2222&#x2F;octosql" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;cube2222&#x2F;octosql</a>
评论 #30858169 未加载
eliben大约 3 年前
Some of the issues pointed out by this (very good) article may already be fixed in tip Go, with <a href="https:&#x2F;&#x2F;go-review.googlesource.com&#x2F;c&#x2F;go&#x2F;+&#x2F;385274" rel="nofollow">https:&#x2F;&#x2F;go-review.googlesource.com&#x2F;c&#x2F;go&#x2F;+&#x2F;385274</a>
throwoutway大约 3 年前
The first code-to-assembly highlighting example here is beautiful. Question to the authors— is that custom just for this article?<p>Is there an open source CSS library or something that does this?
评论 #30857815 未加载
jatone大约 3 年前
what I expect to happen now that golang has generics and reports like these will show up is golang will explore monomorphizing generics and get hard numbers. they may also choose to use some of the compilation speeds they&#x27;ve gained from linker optimizations and spend that on generics.<p>I can&#x27;t imagine monomorphizing being that big of a deal during compilation if the generation is defered and results are cached.
评论 #30857863 未加载
sedatk大约 3 年前
This is a great article yet with an unnecessarily sensationalist headline. Generics can be improved in performance over time, but a superstition like &quot;generics are slow&quot; (not the exact headline, but what it implies to reader) can remain stuck in our heads forever. I can see developers stick to the dogma of &quot;never use generics if you want fast code&quot;, and resorting to terrible duplication, and more bugs.
eatonphil大约 3 年前
Key tldr from me:<p>&gt; Ah well. Overall, this may have been a bit of a disappointment to those who expected to use Generics as a powerful option to optimize Go code, as it is done in other systems languages. We have learned (I hope!) a lot of interesting details about the way the Go compiler deals with Generics. Unfortunately, we have also learned that the implementation shipped in 1.18, more often than not, makes Generic code slower than whatever it was replacing. But as we’ve seen in several examples, it needn’t be this way. Regardless of whether we consider Go as a “systems-oriented” language, it feels like runtime dictionaries was not the right technical implementation choice for a compiled language at all. Despite the low complexity of the Go compiler, it’s clear and measurable that its generated code has been steadily getting better on every release since 1.0, with very few regressions, up until now.<p>And remember:<p>&gt; DO NOT despair and&#x2F;or weep profusely, as there is no technical limitation in the language design for Go Generics that prevents an (eventual) implementation that uses monomorphization more aggressively to inline or de-virtualize method calls.
评论 #30857929 未加载
fulafel大约 3 年前
&gt; Inlining code is great. Monomorphization is a total win for systems programming languages: it is, essentially, the only form of polymorphism that has zero runtime overhead<p>Blowing your icache can result in slowdowns. In many cases it&#x27;s worth having smaller code even if it&#x27;s a bit slower when microbenchmarked cache-hot, to avoid evicting other frequently used code from the cache in the real system.
评论 #30859895 未加载
ribit大约 3 年前
Monomorphisation is a double-edged blade. Sometimes keeping the code smaller and hot is better than inlining everything, especially when your application does not exclusively own all the system resources (an assumption that many “systems programming languages” sadly do). There is too much focus on “performance” aka. microbenchmarks, but they don’t tell you the whole story. If you have a heavily async environment, with multiple tasks running in parallel and waiting on each other in complex patterns, more compact, reusable code can not only speed up the work but also allow you to do more work per watt of energy.<p>I think it’s great that golang designers decided to follow Swift’s approach instead of specializing everything. The performance issues can be fixed in time with more tools (like monomorphissation directives) and profile-guided optimization.
dse1982大约 3 年前
This is a very interesting article. I was however a bit confused by the lingo, calling everything generics. As I understood it the main point of the article quite precisely matched the distinction between generics and templates as I learned it. Therefore what surprised me most was the fact that go monomorphizes generic code sometimes. Which however makes sense given the way go&#x27;s module-system works – i.e. imported modules are included in the compilation – but doesn&#x27;t fit my general understanding of generics.
评论 #30864587 未加载
maxekman大约 3 年前
Similar to how the GC has become faster and faster with each version, we can expect the generics implementation to be too. I wouldn’t pay much attention to conclusions about performance from the initial release of the feature. The Go team is quiet open with their approach.
morelisp大约 3 年前
&gt; there’s no incentive to convert a pure function that takes an interface to use Generics in 1.18.<p>Good. I saw a lot of people suggesting in late 2021 that you could use generics as some kind of `#pragma force-devirtualization`, and that would be awful if it became common.
评论 #30860685 未加载
YesThatTom2大约 3 年前
People that demanded generics don’t care about performance.<p>They care about making excuses about not using Go.
ctvo大约 3 年前
Bravo on the informative content and presentation. That component that shows the assembly next to syntax highlighted code? <i>chefs kiss</i>
hu3大约 3 年前
Related. The introduction of Generics in Go revived an issue about the ergonomics of typesafe Context in a Go HTTP framework called Gin: <a href="https:&#x2F;&#x2F;github.com&#x2F;gin-gonic&#x2F;gin&#x2F;issues&#x2F;1123" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;gin-gonic&#x2F;gin&#x2F;issues&#x2F;1123</a><p>If anyone can contribute, please do.
slackfan大约 3 年前
Meh. The people who screamed loudest about Generics missing in Go aren&#x27;t going to be using the language now that the language has them, and are going to find something new to complain about.<p>The language will suffer now with additional developmental and other overhead.<p>The world will continue turning.
kubb大约 3 年前
Reading the title I&#x27;m worried, should I keep using reflection instead?
评论 #30857522 未加载
评论 #30857798 未加载
评论 #30857345 未加载
评论 #30857626 未加载
评论 #30857432 未加载
评论 #30858597 未加载
评论 #30857465 未加载
zellyn大约 3 年前
(off-topic) Anyone else using Firefox know why the text starts out light gray and then flashes to unreadably dark gray after the page loads? (The header logo and text change from gray to blue too)
评论 #30857905 未加载
torginus大约 3 年前
This is essentially how C# generics have worked since forever. If you want performance, don&#x27;t use pointer type arguments.
jimmaswell大约 3 年前
&gt; you create an exciting universe of optimizations that are essentially impossible when using boxed types<p>Couldn&#x27;t JIT do this?
kevwil大约 3 年前
Seems obvious; like, did someone expect all the extra abstraction would make Go faster?
评论 #30860239 未加载
评论 #30859741 未加载
评论 #30861289 未加载
lokar大约 3 年前
It seems like the code size vs speed trade-off would be well managed by FDO.
AtNightWeCode大约 3 年前
Is there any large project that done an in-place replacement to use generics that has been benchmarked? I doubt that the change is even measurable in general.
ki_大约 3 年前
Generics are a generic solution, but they are absolutely necessary in my opinion.
ramesh31大约 3 年前
Well sure. Not writing hand tuned assembly can make your code slower, too. Go&#x27;s value as a language is how it fills the niche between Rust and Python, giving you low level things like manual memory control, while still making tradeoffs for performance and developer experience.
评论 #30857760 未加载