Live data from Hacker News

Generics can make your Go code slower

planetscale.com

391–400 of 418 posts

Re: Generics can make your Go code slower

#391
post #197
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…

Let’s start at the beginning. What is a «systems language» and for what is it typically used?

Something that is used to write an OS, low level programming, low memory footprint, high performance/optimized.

Re: Generics can make your Go code slower

#392
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…

I agree.

There are just not enough statically typed languages that don't use a GC.

Re: Generics can make your Go code slower

#393
post #268

Earlier quoted context omitted.

You're right, here's what one of my hot loops look like: func (cc *ComponentContainer[T]) ForEach(f func(*Component[T])) { for _, page := range cc.pool.pages { for i := range page { if page[i].IsActive() { f(&page[i]) } } } } Still, the interface approach is a total nightmare from a readability + runtime error perspective so I won't be going back & will just hope for some performance freebies in 1.19 or later :^)

Just to clarify things here: a pointer receiver on a generic type isn't what was covered in the article. That was covering if your `T` is a pointer type. If T here is a value-type, you're probably getting monomorphization (at the cost of copying the value all over, and possible benefit of inlining to reduce that copying).

Thanks, that makes more sense!

My components are all small structs (coordinates, states, health values, etc) so I am happy to copy them around

Component[T] is something like

    {
        Metadata_fields...
        Data T
    }

Re: Generics can make your Go code slower

#394
post #81

Earlier quoted context omitted.

You really haven't given any supporting information for your argument other than a vague feeling that GC is somehow bad. In fact you just pointed out many counterexamples to your own argument, so I'm not sure what to take away. 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. On the other hand…

Virtually invariably, "GC is bad" assumes (1) lots of garbage (2) long pause times. Go has idiomatic value types (so it generates much less garbage) and a low-latency garbage collector. People who argue against GC are almost always arguing against some Java GC circa 2005.

What do you consider a long pause time?

In userland I consider anything above maybe 1 or 2 milliseconds to be a long pause time. The standards only get higher when it's something like a kernel.

A kernel with even a 0.2ms pause time can be unacceptable when working with ultra low-latency audio for example.

Re: Generics can make your Go code slower

#395
post #118

Go does has some form of monomorphization implemented in Go1.18; it is just behind a feature flag(compiler flags). Look at the assembly difference between this two examples: 1. https://godbolt.org/z/7r84jd7Ya (without monomorphization) 2. https://godbolt.org/z/5Ecr133dz (with monomorphization) If you don't want to use godbolt, run the command `go tool compile '-d=unified=1' -p . -S main.go` I guess that the flag is n…

I feel like a half-idiot but I'm unable to tell how exactly the "unified=1" implements monomorphization. I don't see the extra indirections which OP writes about.

Re: Generics can make your Go code slower

#396

Earlier quoted context omitted.

Virtually invariably, "GC is bad" assumes (1) lots of garbage (2) long pause times. Go has idiomatic value types (so it generates much less garbage) and a low-latency garbage collector. People who argue against GC are almost always arguing against some Java GC circa 2005.

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…

Not to detract from your general point, but I believe that this specific situation was addressed in Go 1.18's GC pacer rework: https://github.com/golang/proposal/blob/master/design/44167-....

Re: Generics can make your Go code slower

#397
post #268

Earlier quoted context omitted.

Just to clarify things here: a pointer receiver on a generic type isn't what was covered in the article. That was covering if your `T` is a pointer type. If T here is a value-type, you're probably getting monomorphization (at the cost of copying the value all over, and possible benefit of inlining to reduce that copying).

Thanks, that makes more sense! My components are all small structs (coordinates, states, health values, etc) so I am happy to copy them around Component[T] is something like { Metadata_fields... Data T }

[deleted]

Re: Generics can make your Go code slower

#398

Earlier quoted context omitted.

> A good portion of production outages are likely related to cascading failures due to too long GC pauses, and a good portion of developer time is spent testing and tuning GC parameters. Can’t really accept that without some kind of quantitative evidence.

No worries. It is not meant to be quantitative. For a few years of my career that has been my experience. For this type of software, if I'm making the decision on what technology to use, it won't be any GC-based language. I'd rather not rely on promises that GC works great, or is very tunable. One could argue that I could just tune my services from time to time. But I'd just reduce the surface area for problems by no…

> I'd rather not rely on promises that GC works great, or is very tunable.

I'm always puzzled by statements like these. What else do you want to rely on? The best answer I can think of is "The promise that my own code will work better", but even then: I don't trust my own code, my past self has let me down too many times. The promise that code from my colleagues will do better than GC? God forbid.

It's not like not having a GC means that you're reducing the surface area. You're not. What you're doing is taking on the responsibility of the GC and gambling on the fact that you'll do the things it does better.

The only thing that I can think of that manually memory managed languages offer vs GC languages is the fact that you can "fix locally". But then again, you're fixing problems created by yourself or your colleagues.

Re: Generics can make your Go code slower

#399
post #391
post #197

Earlier quoted context omitted.

Let’s start at the beginning. What is a «systems language» and for what is it typically used?

Something that is used to write an OS, low level programming, low memory footprint, high performance/optimized.

When you say OS, do you mean kernel or kernel and the daemons?

Re: Generics can make your Go code slower

#400

Earlier quoted context omitted.

Virtually invariably, "GC is bad" assumes (1) lots of garbage (2) long pause times. Go has idiomatic value types (so it generates much less garbage) and a low-latency garbage collector. People who argue against GC are almost always arguing against some Java GC circa 2005.

What do you consider a long pause time? In userland I consider anything above maybe 1 or 2 milliseconds to be a long pause time. The standards only get higher when it's something like a kernel. A kernel with even a 0.2ms pause time can be unacceptable when working with ultra low-latency audio for example.

The criticisms I've heard typically reference pause times in the tens or hundreds of milliseconds. Agreed that different domains and applications have different requirements for pause times. I would be very interested to see histograms of pause times for different GCs, but I'm pretty sure the specific results would vary a lot depending on the specific corpus of applications under benchmark. If your 99%-ile pause time is tens of microseconds, is that good enough for video games? Audio kernels?
Post reply on HN