Live data from Hacker News

Generics can make your Go code slower

planetscale.com

221–230 of 418 posts

Re: Generics can make your Go code slower

#221

Earlier quoted context omitted.

This is the no true scottsman argument. I mean, no true modern GC. And it's bullshit. Let's be topical and pick on Go since that's the language in the title: https://blog.twitch.tv/en/2019/04/10/go-memory-ballast-how-i... 30% of CPU spent on GC, individual GC pauses already in the milliseconds, despite a tiny half-gig heap in 2019. For gamedev, a single millisecond in the wrong place can be enough to miss vsync and h…

I don't think you know what "no true scotsman" means--I'm not asserting that Go's GC is the "true GC" but that it is one permutation of "GC" and it defies the conventional criticisms levied at GC. As such, it's inadequate to refute GC in general on the basis of long pauses and lots of garbage, you must refute each GC (or at least each type/class of GC) individually. Also, you can see how cherry-picking pathological,…

> I don't think you know what "no true scotsman" means--I'm not asserting that Go's GC is the "true GC"

At no point in invoking https://en.wikipedia.org/wiki/No_true_Scotsman does one bother to define what a true scotsman is, only what it is not by way of handwaving away any example of problems with a category by implying the category excludes them. It's exactly what you've done when you state "People who argue against GC are almost always arguing against" some ancient, nonmodern, unoptimized GC.

Modern GCs have perf issues in some categories too.

> As such, it's inadequate to refute GC in general on the basis of long pauses and lots of garbage, you must refute each GC (or at least each type/class of GC) individually.

I do not intend to refute the value of GCs in general. I will happily use GCs in some cases.

I intend to refute your overbroad generalization of the anti-GC camp, for which specific examples are sufficient.

> Also, you can see how cherry-picking pathological, worst-case examples doesn't inform us about the normative case, right?

My examples are neither pathological nor worst case. They need not be normative - but for what it's worth, they do exemplify the normative case of my own experiences in game development across multiple projects with different teams at different studios, when language level GCs were used for general purpouses, despite being bypassed for bulk data.

It's also exactly what titzer was complaining was missing upthread:

> I've seen this sentiment a lot, and I never see specifics. "GC is bad for systems language" is an unsupported, tribalist, firmly-held belief that is unsupported by hard data.

Re: Generics can make your Go code slower

#222
post #46

I'd argue that golang is inherently not a systems language, with its mandatory GC managed memory. I think it'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/C++/Rust/D are all superior for that kind of application. All of which is to say, I don't think it matters. Use t…

Hold the phone. Where did the leap from “golang is not a systems language” to “poor choice for anything performance or memory sensitive” come from?

That is a huge leap you are making there that I don’t think is exactly justified.

Re: Generics can make your Go code slower

#223

Earlier quoted context omitted.

> easily implement for your own types have you ever actually done that? I have, its not easy. Please dont try to hand wave away negatives of the Rust type system.

> have you ever actually done that? I have, its not easy. Yes. I do it frequently. "#[derive(Error, Debug)]": https://github.com/dtolnay/thiserror#example Much easier than implementing the error interface in go. Rust is powerful enough to allow macros to remove annoying boiler-plate, and so most people using rust will grab one of the error-handling crates that are de-facto standard and remove the minor pain you're ta…

> Much easier than implementing the error interface in go.

is this a joke? You have to import a third party package, just to implement an error interface? Here is Go example, no imports:

    type errorString string

    func (e errorString) Error() string {
       return string(e)
    }

Re: Generics can make your Go code slower

#224
post #212

Earlier quoted context omitted.

I've heard the exact opposite. The supposed performance benefits of JIT compared to AOT (profile-guided optimization, run-time uarch-targeted optimization) never really materialized. There's been a lot of research since the late '90s into program transformation and it turned out that actually the most effective optimizations are architecture-independent and too expensive to be performed over and over again at startup…

Good luck with inlining and devirtualization across DLLs with AOT. JIT caches with PGO get most of AOT benefits, that is why after the short stint with AOT on Android, Google decided to invest in JIT caches instead. The best toolchains can do both, so it is never a matter of either AOT or JIT. GCC and clang aren't investing in JIT features just for fun.

What's with the snappy tone?

>Good luck with inlining and devirtualization across DLLs with AOT.

An AOT compiler/linker is unable to inline calls across DLL boundaries because DLLs present a black-box interface. A JIT compiler would run into the exact same problem when presented with a DLL whose interface it doesn't understand or is incompatible with. If you really want a call inlined the solution is to link the caller and function statically (whether the native code generation happens at compile- or run-time), not to depend on unknown capabilities of the run-time.

>The best toolchains can do both, so it is never a matter of either AOT or JIT.

You're refuting a false dichotomy no one raised.

Re: Generics can make your Go code slower

#225
post #46

I'd argue that golang is inherently not a systems language, with its mandatory GC managed memory. I think it'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/C++/Rust/D are all superior for that kind of application. All of which is to say, I don't think it matters. Use t…

Go is a system (no s) language IMO.

Re: Generics can make your Go code slower

#226
post #216

Earlier quoted context omitted.

This is the no true scottsman argument. I mean, no true modern GC. And it's bullshit. Let's be topical and pick on Go since that's the language in the title: https://blog.twitch.tv/en/2019/04/10/go-memory-ballast-how-i... 30% of CPU spent on GC, individual GC pauses already in the milliseconds, despite a tiny half-gig heap in 2019. For gamedev, a single millisecond in the wrong place can be enough to miss vsync and h…

From your link (which I remember reading at the time): > So by simply reducing GC frequency, we saw close to a ~99% drop in mark assist work, which translated to a~45% improvement in 99th percentile API latency at peak traffic. Did you look at the actual article? (Because it doesn't support your point). They added a 10GB memory ballast to keep the GC pacer from collecting too much. That is just a bad heuristic in the…

> Did you look at the actual article? (Because it doesn't support your point).

I did and it does for the point I intended to derive from said article:

>> However, the GC pause times before and after the change were not significantly different. Furthermore, our pause times were on the order of single digit milliseconds, not the 100s of milliseconds improvement we saw at peak load.

They were able to improve times via tuning. Individual GC pause times were still in the milliseconds. Totally acceptable for twitch's API servers (and in fact drowned out by the several hundred millisecond response times), but those numbers mean you'd want to avoid doing anything at all in a gamedev render thread that could potentially trigger a GC pause, because said GC pause will trigger a vsync miss.

> I'd argue a tuning knob isn't so bad, compared to rewriting your entire application to manually malloc/free everything, which would likely result in oodles of bugs.

Memory debuggers and RAII tools have ways to tackle this.

I've also spent my fair share of time tackling oodles of bugs from object pooling, meant to workaround performance pitfalls in GCed languages, made worse by the fact that said languages treated manual memory allocation as a second class citizen at best, providing inadequate tooling for tackling the problem vs languages that treat it as a first class option.

Re: Generics can make your Go code slower

#227
post #88
post #77

Earlier quoted context omitted.

C++ can suffer from negative performance from template bloat in two ways: Templated symbol names are gigantic. This can impact program link and load times significantly in addition to the inflated binary size. Duplication of identical code for every type, for example the methods of std::vector and std::vector should compile to the same instructions. There are linker flags that allow some deduplication but those have…

> There are linker flags that allow some deduplication but those have their own drawbacks As long as you use --icf=safe I don't see any drawback, and most of the time it results in almost identical reductions to --icf=all since not many real programs compare addresses of functions.

I think that requires separate function sections, which themselves may cause bloat and data duplication.

Re: Generics can make your Go code slower

#228

Earlier quoted context omitted.

The article is from a database company, so I'll assume that approximates the scope. My scope for the GC discussion would include other parts that could be considered similar software: cluster-control plane (Kubernetes), other databases, and possibly the first level of API services to implement a service like an internal users/profiles or auth endpoints. The tricky thing is GC works most of the time, but if you are wo…

Go doesn’t offer a bunch of GC tuning parameters. Really only one parameter, so your concerns about complex GC tuning here seem targeted at some other language like Java. This is a drawback in some cases, since one size never truly fits all, but it dramatically simplifies things for most applications, and the Go GC has been tuned for many years to work well in most places where Go is commonly used. The developers of…

Is go's GC not copying/generational? I think "stack allocation" doesn't really make sense in a generational GC, as everything sort of gets stack allocated. Of course, compile-time lifetime hints might still be useful somehow.

Re: Generics can make your Go code slower

#230

Earlier quoted context omitted.

Go doesn’t offer a bunch of GC tuning parameters. Really only one parameter, so your concerns about complex GC tuning here seem targeted at some other language like Java. This is a drawback in some cases, since one size never truly fits all, but it dramatically simplifies things for most applications, and the Go GC has been tuned for many years to work well in most places where Go is commonly used. The developers of…

Is go's GC not copying/generational? I think "stack allocation" doesn't really make sense in a generational GC, as everything sort of gets stack allocated. Of course, compile-time lifetime hints might still be useful somehow.

> Is go's GC not copying/generational?

Nope, Go does not use a copying or generational GC. Go uses a concurrent mark and sweep GC.

Even then, generational GCs are not as cheap as stack allocation.

Post reply on HN