Live data from Hacker News

Making a Go program faster with a one-character change

hmarr.com

151–160 of 249 posts

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

#151
post #112

Earlier quoted context omitted.

70% slower is a bit ambiguous though - it could mean 70% extra runtime or it could mean 30% of the new speed. Whereas 70% faster would always suggest to me that it can do 70% more work in the same amount of time, i.e. a 1.7x increase in speed.

I do not agree. When you benchmark you usually measure the differences between times needed to complete. This is because it is highly non-obvious that if you increase workload twice, the time increases also twice. Perhaps the algorithm is not linear. Perhaps if you have more data, you suddenly need to swap memory. Perhaps something (like disk access in parallel) means that actually it takes less than 2x time. This me…

But under your definition, if something becomes "three times as fast" (i.e., 200% faster), it will have to finish its task in negative time!

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

#152
post #141

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…

That's not a deeper lesson. A deeper lesson is to understand where the pointer points to and then decide accordingly.

That is pretty much what I said, except phrased different.

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

#153
post #112

Earlier quoted context omitted.

70% slower is a bit ambiguous though - it could mean 70% extra runtime or it could mean 30% of the new speed. Whereas 70% faster would always suggest to me that it can do 70% more work in the same amount of time, i.e. a 1.7x increase in speed.

I do not agree. When you benchmark you usually measure the differences between times needed to complete. This is because it is highly non-obvious that if you increase workload twice, the time increases also twice. Perhaps the algorithm is not linear. Perhaps if you have more data, you suddenly need to swap memory. Perhaps something (like disk access in parallel) means that actually it takes less than 2x time. This me…

I can categorically state I've never thought of or understand 70% faster as meaning that, and certainly not 100% faster as meaning "completes instantly".

I see the OP has solved the problem by removing any references to how much faster from the article title!

You're right about non-linear algorithms though. If an O(n^2) algorithm is 2x / 100% faster, it can't process 100% more items in the same time, but I'd understand it to mean taking half the time for the same n.

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

#154

So, this is very basic Go design and you could write something about how it works in C and Go and why a older lang like C don't have this prob but then at the end of the day the Go fanclub will down vote the hell out you no matter what.

Go compiler is garbage by the design. A 20 year old C compiler does not have this prob. This is also why Go have declined so much during the last couple of years. The benefits of Go have not increased and most of the quirks are still there. Like the error handling, the naive compiler and the syntax sugar that somewhat hides the diff between pointers and direct heap allocs. -1

I work on a code base that is a mixture of Go and C.

It's IO, CPU and Memory hungry, and it's distributed.

C is fast because it's close to how CPU and memory actually work. Go gives you 95+% of that plus easy to learn, easy to use language. A new person could start contributing useful features and bug fixes immediately. A senior person could get C-level performance.

More and more of our code is moved from C to Go, with very little performance penalty, but with a lot more safety and ease of use.

Our customers benefit, and our company makes more money.

In the end, that's what software is about.

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

#155

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…

> but it puts a lot more pressure on the GC than simple local stack variables.

Do you have evidence for this claim? AFAIK the Go compiler does escape analysis, and allocates pointers that don't escape on the stack.

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

#156
post #21

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

The performance issue here is not value semantics, it's the overhead of automatic lifetime management. The copy is cheap. The lifetime tracking is not because it forces a heap allocation and creates additional GC pressure. In fact, assuming Rule is small, if Match returned by value , the code would be similarly as fast.

> The performance issue here is not value semantics

There's no performance cost to value semantics, so of course not.

> The copy is cheap. The lifetime tracking is not because it forces a heap allocation and creates additional GC pressure. In fact, assuming Rule is small, if Match returned by value, the code would be similarly as fast.

I'm referring more to how this stuff seeps in without the programmer realizing it. It's the implicit nature of all this behaviour that is the problem.

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

#157
post #134

Earlier quoted context omitted.

The one place where you’ll actually see this is in Read(). If you try to read 1000 bytes, you might get “800 bytes read, EOF” as a result. The worst part is that os.File won’t ever do this!

I really hate when people use "errors" for signals. Or, alternately, use the signals mechanisms for actual errors. An error should be "something went wrong", and reading a file to the EOF is not "going wrong", that's just what the "read()" should do if you tell it so! I like Go's multiple returns and error checking by default, but it definitely should have been implemented with some sort of "Result/Error" type union…

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.

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

#158

Earlier quoted context omitted.

The performance issue here is not value semantics, it's the overhead of automatic lifetime management. The copy is cheap. The lifetime tracking is not because it forces a heap allocation and creates additional GC pressure. In fact, assuming Rule is small, if Match returned by value , the code would be similarly as fast.

> The performance issue here is not value semantics There's no performance cost to value semantics, so of course not. > The copy is cheap. The lifetime tracking is not because it forces a heap allocation and creates additional GC pressure. In fact, assuming Rule is small, if Match returned by value, the code would be similarly as fast. I'm referring more to how this stuff seeps in without the programmer realizing it.…

Sorry, because of value semantics. (Also, you wrote "performance costs of inopportune value semantics". So the correction is annoying; you know what I meant.)

This stuff seeps in without the programmer realizing it because Go made a deliberate design decision to have automatic lifetime management. In other words, this is a feature of the language and not a bug. The only way for this to not seep in is if Go forced programmers to specify most lifetimes, which would make the language much more cumbersome to use.

I.e., this is not a value-vs-reference semantics issue. It's a manual-lifetime-management vs automatic-lifetime-management issue. The solution is to either 1) write in a language with more explicit lifetimes if performance is that important, or 2) profile your code and reduce heap allocations, which is what the person who wrote the article did.

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

#159
post #130

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

Yup, it's definitely a bit of a code smell if you do. The issue is more the reverse, though - I can't make a mutable map, then hand it by pointer/reference to something that says it wants an immutable map later.

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

#160

Earlier quoted context omitted.

It's not always so bad :) https://play.rust-lang.org/?version=stable&mode=debug&editio...

Now try to actually do that in a larger program without static lifetimes...

It shouldn't be too bad as long as you keep in mind that it is a reference to an item in that slice, so whatever that slice is pointing to needs to stick around as long as you're using elements from it. I don't often encounter borrow checker issues anymore, because once you program Rust long enough you know what things need to live for what lifetimes, and you architect your "larger programs" around that.
Post reply on HN