The deeper lesson here is "don't use pointers unless you're sure you need them". I've seen quite a few people use pointers for no reason in particular, or there's simply the assumption it's faster (and have done this myself, too), but it puts a lot more pressure on the GC than simple local stack variables. Of course sometimes pointers are faster, or much more convenient. But as a rule of thumb: don't use pointers unl…
Making a Go program faster with a one-character change
141–150 of 249 posts
Re: Making a Go program faster with a one-character change
#142Earlier quoted context omitted.
Agreed. Could you Imagine a Java where you have a `Map` and a `MutableMap` and that's what you put at your API? I'd make it SO much clearer how safe any individual API is to call.
In general this doesn't work, the history rule says mutable types are not proper subtypes of immutable ones (and the converse is obvious). If you want to capture mutability in your type system, it needs to be orthogonal to subtyping (like C/C++ const).
I'm unfamiliar with this rule (and not finding anything good to google). Can you elaborate?
I can't really think of a scenario where an immutable datastructure isn't a subset of actions against a mutable datastructure.
Re: Making a Go program faster with a one-character change
#143Would be interesting to see the performance difference if you undo that move-&-change and change the function signature from: func (r Ruleset) Match(path string) (*Rule, error) to: func (r *Ruleset) Match(path string) (*Rule, error)
type Ruleset []Rule
The original code creates a local copy of a rule and explicitly returns a pointer to that. Taking the ruleset by address wouldn't change that issue.Re: Making a Go program faster with a one-character change
#144Earlier quoted context omitted.
Java has been tunable for a long time. Periodically, the recommended tuning changes, or new GC algorithms become available, etc. But it has long been possible to get short pause times with various combinations of choosing the right algorithm and writing your program the right way. I think what really throws people off here is that getting good performance out of a Java application involves some skills which are alien…
Agreed, but usually tuning for short pause times involves trading off throughput or allocation performance. But at the end of the day, if you aren't allocating a bunch of garbage in the first place, then you don't need to be as concerned about the costs of allocating or cleaning up the garbage. I wish Go did more to make allocations explicit so they could be more easily recognized and avoided; I dislike Java's approa…
I’ve had no issues with Java 17+ under heavy allocation/garbage collection (data encryption pipeline I haven’t tuned to reuse buffers yet), and it’s pause times are on the order of a handful of milliseconds, without meaningful tuning. I think it’s doing something like a GB/s of garbage collection.
And the jvm in question is doing a LOT more than just this, so it’s coping with millions of allocated objects at the same time.
Re: Making a Go program faster with a one-character change
#145Earlier quoted context omitted.
C++ still has this problem - std::unordered_map ` and `std::unordered_map ` are basically unrelated types - you can't const-cast the templated const away. (I may be misunderstanding here)
> you can't const-cast the templated const away. That seems like a good thing. If you're handed a map to const values you can't just go "imma gunna mutate them anyway".
Re: Making a Go program faster with a one-character change
#146Earlier quoted context omitted.
> When I write code, it's common to have references to immutable classes thrown around with wild abandon, heedless of ownership, threads, or good taste, because the data just can't change. If there's anything I wish languages with implicit reference semantics would adopt, it's implicit immutability. I wish Java would be so much nicer with keyword that is half way between "final" and "volatile" that means, "yes, you c…
Agreed. Could you Imagine a Java where you have a `Map` and a `MutableMap` and that's what you put at your API? I'd make it SO much clearer how safe any individual API is to call.
Re: Making a Go program faster with a one-character change
#147Don't feel too silly. Russ Cox, one of the technical leads on the Go language, made the same mistake in the regexp package of the standard library.
Re: Making a Go program faster with a one-character change
#148Went from 4.139s to 2.413s. I fail to see how it is 70%. I think it is explained as 4.139/2.413 = 1.7 which of course doesn't make sense here.
Re: Making a Go program faster with a one-character change
#149As an old C/C++ programmer, I'm always surprised by how often software developers are surprised by the performance costs of inopportune value semantics (C and C++ even more so, punishes you severely for using value semantics when you shouldn't). I increasingly see the wisdom of languages with implicit reference semantics. It's not that value semantics can't be better (they most assuredly can be), or that reference se…
I'm a dumb dumb. Can you define "implicit reference semantics" and "value semantics"? You use the phrases several times in your post, but I don't really understand what you mean. If it helps, I'm not a C++ programmer, but I am familiar with higher level languages like Go, Python, Ruby, PHP and Javascript.
Re: Making a Go program faster with a one-character change
#150Overall good review of profiling tactics . But there’s nothing egregious about Golang here . Pass by value vs reference is a common performance issue.
The trap here is that everything is passed by reference (pointer), but the intermediate local value is, well, a value (a copy).
Rule is not a gigantic monster struct (it's 72 bytes), chances are returning it by value would not have been an issue.
Anyway I would say there is an issue with Go here: it's way too easy to copy out of a slice.