Live data from Hacker News

Making a Go program faster with a one-character change

hmarr.com

231–240 of 249 posts

Re: Making a Go program faster with a one-character change

#231
post #3

That seems like a potential for compiler optimization. It should already know that the rule value is only used one time, as the target of a & and this must be somewhat common in managing return values.

Nah an optimization is dangerous as others have said. A lint that detects oversized copies could be worthwhile though.

Re: Making a Go program faster with a one-character change

#232
post #227

Earlier quoted context omitted.

Yeah, I’m nominally familiar with these, but I can’t understand why one of these low latency collectors wouldn’t be the default GC unless they impose other significant tradeoffs.

Naturally there are tradeoffs, for example the amount of infrastruture they need only justifies when one is working at such scale, for example ZGC requires large pages and makes use of NUMA if available.

Sure, but isn't Shenandoah more "general purpose" or whatever?

Re: Making a Go program faster with a one-character change

#233

Earlier quoted context omitted.

If you take the position that the semantics of read() are 'read data from this endless stream', then EOF is an error indicating that this model no longer applies. Doesn't bother me at all.

Except in that model it would be fine to return an error as soon as soon as you know there is an EOF while in the real world you do want to read right up to the EOF because EOF is usually not an error condition but expected, even with streams of indeterminate length.

The model is that you don’t know there’s an EOF until after you’ve read the last data byte.

Re: Making a Go program faster with a one-character change

#234

Earlier quoted context omitted.

I created this video on concurrency (maybe advanced) patterns a while back that some may find helpful but it's pretty long https://www.youtube.com/watch?v=U3_2xiPxyA8 .

This was really good. You should do more of these. Cheers.

Thanks so much! I'd love to once I can find more time :)

Re: Making a Go program faster with a one-character change

#235

Earlier quoted context omitted.

The way to fix it in that manner here is to undo the 42% speedup and return the heap allocated object for the caller to mangle.

Yes, if you are serious about backwards compat then you pay that cost and perhaps add a separate function that is faster for callers to opt into.

Effectively deprecating the old one and recommending the new one being a way to smoothly 'fix' an API.

Re: Making a Go program faster with a one-character change

#236
post #217
post #51

Earlier quoted context omitted.

In C, “discarding” a pointer in a way that leaves the value visible is quite common. At least if one doesn’t accidentally use the pointer, it’s harmless. (In the way that all manner of unsafeness is harmless in C as long as no actual UB occurs, which is to say it’s not great.) But Go is a garbage collected language, and there is so such thing as “discarding” a pointer. Either it’s there or it isn’t, and this kind of…

>and this kind of leak has side effects Only if the calling function does something with the pointer (which it generally won't, if err is non-nil). If the calling code does do something with the pointer even when err is non-nil, then either (a) the value of the pointer is meaningful, and this is fine; or (b) there's a logic error in the calling code, which is a far more serious bug than a potential memory leak. So I…

I should have been more explicit. Go is garbage collected. If you keep a pointer live, then it’s not garbage, which prevents it from being collected.

At least Go doesn’t use RAII, so inadvertently pinning a pointer won’t keep a socket open or a lock held.

Re: Making a Go program faster with a one-character change

#237

Aaaaaand that's why I love Rust's decision to make copies explicit with `.clone()`. Annoying as hell when you're not used to it but overall worth it.

Except a lot of structs also derive and prefer `Copy` and a lot of rust code also avoids heap allocation which requires `Clone`. The `Copy` trait can be used implicitly like in the example here. On the other hand, due to the lack of garbage collector, you wouldn't be able to return the reference to the copy which might lead you to find your accidental copy.

I have yet to come on structs that implement `Copy` while being expensive to actually copy. The largest I can think of is `Uuid` from the `uuid` crate, which is 128 bits in size. This is a single word copy for most machines since modern hardware has 128 bit support for case like this. Still, two 64-bit words to copy is definitely negligible: that's equivalent of copying two pointers.

I agree with you for the garbage collector. By design, a GC allows you to willy-nilly copy without thinking about the consequences.

Re: Making a Go program faster with a one-character change

#238
post #228
post #176

Earlier quoted context omitted.

I had to look it up too, it apparently is a constraint for subtypes defined in Liskovs substitution principle [1]. From Wikipedia: > History constraint (the "history rule"). Objects are regarded as being modifiable only through their methods (encapsulation). Because subtypes may introduce methods that are not present in the supertype, the introduction of these methods may allow state changes in the subtype that are n…

Just curious, isn't it obvious from a logical standpoint? I don't see how one could consider a mutable type to be a subtype of an immutable one. On the other hand, an immutable subtype of a mutable one seem plausible?

Immutable from a mutable is just as implausible. You cannot remove a method from a subtype which results in mutating methods being disabled through other means (like throwing exceptions).

This is also a violation of LSP and the open close principle.

Consider a `List` with an `add` function. What would you do with that `add` function to make an `ImmutableList` subtype?

Re: Making a Go program faster with a one-character change

#239
post #174

Earlier quoted context omitted.

That only matters if you're storing it. The big issue is 99% of code out there uses mutable template types for containers, and if you ever declare a container that doesn't have a mutable template type, you stub your toe as your new container isn't compatible with anyone else's code. You can't even easily copy your way out. std::unordered_map m; m["foo"] = "bar"; std::unordered_map m2 = m; doesn't compile.

> That only matters if you're storing it. Or if you (or something you call) mutate it trough another reference/pointer. Sometimes I wish there was a stronger const where the compiler (and programmer) could actually assume the object is not mutated while that reference/pointer is alive. Of course checking that is no longer doable with just the type system. > You can't even easily copy your way out. That depends on the…

Sure certainly, copying via iterators work, it's just sad and very not implicit.

Re: Making a Go program faster with a one-character change

#240
post #208

Earlier quoted context omitted.

If one cares about pause times, G1 isn't it, rather the pauseless ZGC, Azul's C4 or Shenodah. Capable of handling TB sized heaps with micro seconds pauses.

Yeah, I’m nominally familiar with these, but I can’t understand why one of these low latency collectors wouldn’t be the default GC unless they impose other significant tradeoffs.

They don’t change it from the default because G1 isn’t terrible and Java has a long history of ensuring backwards compatibility - not just in APIs, but also behavior, warts and all.

If they changed the default GC, a lot of folks would freak out, even if it was objectively better in nearly every situation. Because someone, somewhere is relying on some weird bug in G1, or whatever and now their software behaves differently, and it’s a problem.

Give it a couple more major revs, and it might still happen. G1 became the default in what, Java 9?

Post reply on HN