Live data from Hacker News

Generics can make your Go code slower

planetscale.com

381–390 of 418 posts

Re: Generics can make your Go code slower

#381

Earlier quoted context omitted.

Go does not put class pointers on stack variables. Neither does Rust or C. The objects are the objects on the stack. No additional metadata is needed. The only time Go has anything like a class pointer for any object on the stack is in the case of something cast to an interface, because interface objects carry metadata around with them. These days, Go doesn’t even stack allocate all non-escaping local variables… some…

> These days, Go doesn’t even stack allocate all non-escaping local variables… sometimes they will exist only within registers! Did you read the article I linked? That's what it says - and this isn't stack allocation, it's SRA. Even 'registers' is overly constrained - they're dataflow edges.

I was addressing your statement that seemed to say class metadata is included in every language when dealing with stack variables. I trusted your earlier statements that this was definitely the case with Java/Truffle. Misunderstandings on my part are entirely possible.

Sorry I haven’t had time to read your article. It’s on my todo list for later.

Re: Generics can make your Go code slower

#382

Earlier quoted context omitted.

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 again…

> 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.

Yes, that is how a NTS works, which is why you should be able to see that my argument isn't one. If I had said the common criticism of GCs ("they have long pause times") is invalid because the only True GC is a low-latency GC, then I would have made an NTS argument. But instead I argued that the common criticism of GCs doesn't refute GCs categorically as GC critics believe, it only refutes high-latency GCs. I'm not arguing that True GCs are modern, optimized, etc, only that some GCs are modern and optimized and the conventional anti-GC arguments/assumptions ("long pause times") don't always apply.

Re: Generics can make your Go code slower

#384
post #90

Earlier quoted context omitted.

> Go has user defined value types which Java does not yet. C# has this. A lot of people overlook C# in this area, probably because until recently, it was not cross-platform.

The games world has understood C# to be a reasonably capable language for a while. But that world often feels disjoint with the enterprise software world where Go has thrived, eating into Java's niche.

> The games world has understood C# to be a reasonably capable language for a while.

Only in unity, the other major engine in the room still uses C++ for performance reasons.

Re: Generics can make your Go code slower

#385
post #362
post #359

Earlier quoted context omitted.

Go module are easy to use, compiling is even more simpler: go build .

If you say so, "HERO: On the Chaos When PATH Meets Modules" https://cs.nju.edu.cn/changxu/1_publications/21/ICSE21_02.pd...

I’ve been writing go since it basically came out. Every single one of you’re comments is anecdotal so here we go. I’ve never, ever, encountered an issue compiling / building go code using modules. You also said in your first argument that you get no access to raw threads then a comment later said you do. It seems like you’re just advocating for people to use java because it’s what you’re comfortable with.

Re: Generics can make your Go code slower

#386

Earlier quoted context omitted.

Go does not put class pointers on stack variables. Neither does Rust or C. The objects are the objects on the stack. No additional metadata is needed. The only time Go has anything like a class pointer for any object on the stack is in the case of something cast to an interface, because interface objects carry metadata around with them. These days, Go doesn’t even stack allocate all non-escaping local variables… some…

> These days, Go doesn’t even stack allocate all non-escaping local variables… sometimes they will exist only within registers! Did you read the article I linked? That's what it says - and this isn't stack allocation, it's SRA. Even 'registers' is overly constrained - they're dataflow edges.

Go isn't just doing SRA, as far as I understood it from your article, though it is certainly doing that too. Go will happily allocate objects on the stack with their full in-memory representation, which does not include any kind of class pointer.

Here is a contrived example that creates a 424 byte struct: https://godbolt.org/z/5cKh7xTzq

As can be seen in the disassembly, the object created in "Process" does not leave the stack until it is copied to the heap in "ProcessOuter" because ProcessOuter is sending the value to a global variable. The on-stack representation is the full representation of that object, as you can also see by the disassembly in ProcessOuter simply copying that directly to the heap. (The way the escape analysis plays into it, the copying to the heap happens on the first line of ProcessOuter, which can be confusing, but it is only being done there because the value is known to escape to the heap later in the function on the second line. It would happily remain on the stack indefinitely if not for that.)

It's cool that Graal does SRA, but Go will actually let you do a lot of work entirely on the stack (SRA'd into registers when possible), even crossing function boundaries. In your SRA blog post example, when the Vector is returned from the function, it has to be heap allocated into a "real" object at that point. Go doesn't have to do that heap allocation, and won’t have to collect that garbage later.

Most of the time, objects are much smaller than this contrived example, so they will often SRA into registers and avoid the stack entirely… and this applies across function boundaries too, from what I’ve seen, but I haven’t put as much effort into verifying this.

Re: Generics can make your Go code slower

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

Next to python it is a system language by comparison and that is what matters ultimately.

Re: Generics can make your Go code slower

#388
post #100

Earlier quoted context omitted.

Go compiles to static binaries. Java needs the JVM. That already is a HUGE difference in "picking the right tool". Also, the JVM is way more heavy and resource intensive than a typical Go program. Go is great for cli tools, servers, and the usual "microservices" stuff, whatever it means to you.

Java can just be AOT compiled as Go, the only difference is that until recently it wasn't a free beer option to do so.

The problem is that a lot of software in the Java world explicitly relies on it not being compiled AOT. Any standard tomcat or jboss/wildfly application for example.

Re: Generics can make your Go code slower

#389

This is a really long and informative article, but I would propose a change to the title here, since "Generics can make your Go code slower" seems like the expected outcome, where the conclusion of the article leans more towards "Generics don't always make your code slower", as well as enumerating some good ways to use generics, as well as some anti-patterns.

In C++, generics (templates) are zero-cost abstractions. So no, generics do not de facto make code slower.

At runtime maybe (although that's also not 100% true) - but I've seen a big project go from being compiled in 10 minutes in our ci, to hours due to the introduction of large features heavily relying on templates. The fix was installing a k8s cluster to run the Jenkins build jobs distributed on bare metal nodes, this wasn't exactly zero-cost.

Re: Generics can make your Go code slower

#390
post #328

Earlier quoted context omitted.

> They're just built for features of Go They're inferior, and do not cover the same grounds (e.g. "enums" in golang are just integer constants, you can't code gen using golang tags, JFR is way way more comprehensive than anything that golang has etc.) The GC selection, JIT, and hot swapping/reloading are features that do not exist in golang, and we've seen what hoops people have to jump through when they face issues…

Enums in Go are inferior but that doesn't stop you from using them in the same way. Of course you can code gen using Go's tags. It's done all the time. As already pointed out, Go has the JFR it needs, not what Java has. Go doesn't need a JITter. Go isn't perfect, but neither is Java or C#. Go code is known for being maintainable and easy for newcomers to read so your last line applies to Java more than Go. But it see…

> Enums in Go are inferior but that doesn't stop you from using them in the same way.

It does, I have to think twice because I know I'm not getting the compile time features that Java offers, and may end up just using strings in an awkward manner.

> Go has the JFR it needs, not what Java has

That doesn't make sense. All programs need the JFR that Java has, otherwise you wouldn't see companies like Datadog doing well.

> But it seems like you want to hate Go. Why?

I've used it in several large projects at my employer, and in every single project, Java would have been a superior alternative. We've had issues that would not have happened in Java due to many things, such as better error handling in Java, enum support, better frameworks and libraries to interact with the DB, etc.

And no, golang is not known for being maintainable, it's just things that some people parrot without proof. It's basically marketing. There's nothing in the language that inherently makes it more maintainable than Java/C#/etc., and in fact, it has many things that make it less maintainable.

Post reply on HN