Live data from Hacker News

Generics can make your Go code slower

planetscale.com

271–280 of 418 posts

Re: Generics can make your Go code slower

#271

Earlier quoted context omitted.

> What's the difference between importing some hundred's of lines from thiserror in rust vs importing the "error" package in go? Again, you're comparing apples and oranges. It seems you didn't see my previous example, here it is again: type errorString string func (e errorString) Error() string { return string(e) }

I addressed that with the start of my comment: "Let's look at a common example: you want to return two different types of errors and have the caller distinguish between them" Yes, your example implements the error interface, but it's not realistic. There is real go code that does that, but that's the reason I have to do string-matching type error handling in go, and frankly it's an argument against the language that…

You never gave a Rust example without using the 200 lines of Rust package.

You didnt do so, because implementing an error interface in Rust is a painful and extremely verbose process. Its not in Go, as I demonstrated.

> bail!("oh no internal error")

another Rust package. Are you unable to just write Rust without importing something?

Re: Generics can make your Go code slower

#272

Earlier quoted context omitted.

> What, exactly, are you saying that Go can't do that Java can? Runtime library addition (plugins) and dependency injection are two big ones. (We can argue the merit separately, but they're not possible in Go) I think if Java had easily distributable static binaries k8s would have stayed Java (it started out as Java).

I believe Go supports DI via Wire ( https://github.com/google/wire ).

Go supports DI by allowing functions with arguments :) Every language with functions supports DI. Wire is just a code-generator version of automatic DI.

Re: Generics can make your Go code slower

#273

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…

If you're needing to fight the GC to prevent crashes or whatever then you have a system design issue not a tooling/language/ecosystem issue. There are exceptions to this but they're rare and not worth mentioning in a broad discussion like this.

Sadly very few people take interest in learning how to design systems properly.

Instead they find comfort in tools that allow them to over-engineer the problems away. Like falling into zealotry on things like FP, zero-overhead abstractions, "design patterns", containerization, manual memory management, etc, etc. These are all nice things when properly applied in context but they're not a substitute for making good system design decisions.

Good system design starts with understanding what computers are good at and what they suck at. That's a lot more difficult than it sounds because today's abstractions try to hide what computers suck at.

Example: Computers suck at networking. We have _a lot_ of complex layers to help make it feel somewhat reliable. But as a fundamental concept, it sucks. The day you network two computers together is the day you've opened yourself up to a world of hurt (think race conditions) - so, like, don't do it if you don't absolutely have to.

Re: Generics can make your Go code slower

#274

Earlier quoted context omitted.

I addressed that with the start of my comment: "Let's look at a common example: you want to return two different types of errors and have the caller distinguish between them" Yes, your example implements the error interface, but it's not realistic. There is real go code that does that, but that's the reason I have to do string-matching type error handling in go, and frankly it's an argument against the language that…

You never gave a Rust example without using the 200 lines of Rust package. You didnt do so, because implementing an error interface in Rust is a painful and extremely verbose process. Its not in Go, as I demonstrated. > bail!("oh no internal error") another Rust package. Are you unable to just write Rust without importing something?

As I said above:

> In this case, the abstraction available in rust is cleaner and requires less code for me, the user of the package, so I don't think the lines of code used to build that abstraction matter.

> Why do you see this as something that matters?

It's true that the abstraction in rust has more code underlying it, but why does that matter?

If you de-facto never have to implement the rust error trait by hand due to excellent library support, then it's a moot point, isn't it?

Anyway, my examples above did implement the error trait, simply by deriving it.

> Are you unable to just write Rust without importing something?

Rust does have less in the stdlib, yes. If you want a json serializer in go, that's the stdlib. In rust, it's the serde package.

Rust is intentionally a smaller standard library. I don't think there's anything wrong with that, and I personally prefer it since it allows for more innovation on things like http / json / error interfaces / etc.

I don't know why you're phrasing it like it's a bad thing.

Re: Generics can make your Go code slower

#275

Earlier quoted context omitted.

From the article: > Monomorphization is a total win for systems programming languages: it is, essentially, the only form of polymorphism that has zero runtime overhead, and often it has negative performance overhead. It makes generic code faster. The point is that the way Go implements generics is in such a way that it can make your code slower, even though there is a well-known way that will not make your code slowe…

>even though there is a well-known way that will not make your code slower (at the cost of compile times). That's the point though. The Golang team was surely aware of both approaches, and chose what they did as a conscious design decision to prefer faster compile times. People love Go because of the iteration speed compared to C++. And these little things start to add up if you don't have a clear product vision abou…

Of course, I understand that they made that decision. I was just replying to this:

> of cause generics can make your code slower, what did people expect.

It's not unreasonable that some people might have expected monomorphization.

Re: Generics can make your Go code slower

#276

Earlier quoted context omitted.

You never gave a Rust example without using the 200 lines of Rust package. You didnt do so, because implementing an error interface in Rust is a painful and extremely verbose process. Its not in Go, as I demonstrated. > bail!("oh no internal error") another Rust package. Are you unable to just write Rust without importing something?

As I said above: > In this case, the abstraction available in rust is cleaner and requires less code for me, the user of the package, so I don't think the lines of code used to build that abstraction matter. > Why do you see this as something that matters? It's true that the abstraction in rust has more code underlying it, but why does that matter? If you de-facto never have to implement the rust error trait by hand…

Thats a good outlook. Dont worry about any problem, just import something an its fixed! More imports the better! Hopefully we can do away with all code, and just import everything.

Re: Generics can make your Go code slower

#277

Earlier quoted context omitted.

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.

Stack's just the youngest generation.

I can see the difference being that you have to scan a generation but the entire stack can be freed at once, but it still seems like an overly specific term. The general term elsewhere for multiple allocations you can free at the same time is "arenas".

Re: Generics can make your Go code slower

#278
post #255

Earlier quoted context omitted.

I have, it's a decent read - although somewhat incoherent. E.g. they tout the benefits of GCing when idle, then trash the idea of controlling GC: > Sin two: explicit garbage-collection invocation. JavaScript does not have a Java-style System.gc() API, but some developers would like to have that. Their motivation is proactively to invoke garbage collection during a non-time-critical phase in order to avoid it later wh…

> So, no explicitly GCing when a game knows it's idle. I mean, that is literally what the idle time scheduler in Chrome does. It has a system-wide view of idleness, which includes all phases of rendering and whatever else concurrent work is going on. > Intertwined references from C++ -> Squirrel[1] -> C++ -> Squirrel meant the first GC would finalize some C++ objects, which would unroot some Squirrel objects, which w…

> I mean, that is literally what the idle time scheduler in Chrome does. It has a system-wide view of idleness, which includes all phases of rendering and whatever else concurrent work is going on.

Roughly, but it has poor insight into a game's definition of "idle". Probably fine for most web games, but prioritizing, say, "non-idle" game-driven prefetching and background decompression over GC can be the wrong tradeoff.

> This is a nasty problem and it happens a lot interfacing two heaps, one GC'd and one not. The solution isn't less GC, it's more. That's why Chrome has GC of C++ (Oilpan) and is working towards a unified heap (this may already be done). You put the blame on the wrong component here.

Two non-GCed heaps doesn't have this problem, nor do two "GC"ed heaps if we use an expansive definition of GC that includes refcounting-only systems - it only arises when using multiple heaps, when at least one of them is the deferred scanny finalizer-laden GC style. While you're correct that "more GC" is a solution, it's not the only solution, it has it's drawbacks, and holding GC blameless here is disingenuous when it's the only common element. That these GCs compose poorly with other heaps is a drawback of said GCs.

If I try mixing Squirrel and C#, I'll run the risk of running into the same issues, despite both being GC based. I'm sure you'll agree that attempting to coax them into using the same heap is a nontrivial endeavor. I've been in the position of having two different JavaScript engines (one for "gameplay", one for UI) in the same project - but they were fortunately used for separate enough things to not create these kind of onion layers of intertwined garbage. While silly from a clean room technical standpoint, it's the kind of thing that can arise when different organizational silos end up interfacing - a preexisting reality I've been inflicted by more than once.

Re: Generics can make your Go code slower

#279
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 would say Go is a systems programming language. A systems programming language is for creating services used by actual end user applications. That is pretty much what Go is being used for. Who is writing editors or drawing applications in Go? Nobody. Go does contain many of the things of interest to systems programmers such as pointers and the ability to specify memory layout of data structures. You can make your o…

I'm not saying this is wrong, because I think what "systems programming" is subjective.

But wouldn't this classify Java as a systems language? Java is used to build DBs and I believe AWS's infrastructure is mostly java. Plus, Java definitely has pointers.

Re: Generics can make your Go code slower

#280
post #150

Earlier quoted context omitted.

In the language? In the implementation?

Both. It can be paused or disabled at runtime.

But then presumably if you disable it you have to have no heap allocation at any time in your program, or manually manage buffers. I feel like that's not worth it.
Post reply on HN