Hacker News new | ask | show | jobs
by cooervo 2919 days ago
So we should avoid defeR?
3 comments

Unless it is a hot path and the CPU is your bottle neck most of these optimizations would make the code less maintainable / less safe and I wouldn't personally do any of them.

What good is fast code if it is unmaintainable?

What good is maintainable, easily extendable, neatly structured code when it's slow and doesn't meet the execution time criteria imposed by your client?
For most products the "time" that matters is "time to market" and "time to resolution" on bugs. Most business uses cases don't require the kind of performance we expect of them.

Depending on industry, time is relative. These optimizations will save you milliseconds on tight loops. In reality most apps aren't spending their time on tight loops. They are spending their time waiting for I/O or using inefficient algorithms. Neither of which these optimizations solve for.

If you are underperforming spec by 100ms it is likely you have one big change you need to make to save 100ms not 100 small micro-optimizations.

As you stated yourself: Most projects, not all. The 1% of project that are performance critical still matter to thousands of engineers.

Only because most people don't have to do this there are still some people that have to do optimzation where possible.

I hope you understand that optimization without profiling is worthless. Once profiling is identifying something like your datastructure as some kind of bottleneck it might be worth a shot investigating that hint.

And these kind of articles are a nice summary of work being done, giving an overview over techniques and small tweaks that you might not have thought about previously.

It is good work by the author and he deserves being recognized for it. Not being dismissed by the bland statement don't waste your time with optimization.

No. Defer has a role, which is to reduce the number of issues related to resource return like closing file descriptors and returning pool objects.

Don't use defer when there is only one branch in your code.

Remove defer when optimising hot code paths.

Please use defer when there is only one code path as well unless it is a hot function and you have measured a noticeable performance decrease.

Code will get changed over time and one code path often becomes two or more. Chances are, the next developer who adds code will not realize that the resource needs to be freed, or closed and simply forgets to add the defer. The only thing where defer really gets into your way is for error handling (because it can get verbose if you handle errors in defer).

In the grand scheme of things, defer is not noticeablily slower.

I was wondering too. Does anybody know what makes defer so expensive?
Memory allocation.

Use defer to make code readable. Go code should be readable, so you can figure out if it is correct, and only then should it be fast.

When benchmarking/profiling leads you to a hot spot in the code, rewrite it to remove defers.

5300+ ns/op is for BenchMarkSize (1024) defer operations, so we are actually paying about 5ns/op for defer. Not sure why the author chose to report the ns/op number in its current way.
"so we are actually paying about 5ns/op for defer"

Yeah, it's in the class of "things you should know about when optimizing tight loops", but not "things you should always be worrying about"; remember 5ns is on the order of a branch mispredict or an L2 cache miss [1]. If you haven't already squeezed out all the main memory accesses you can from your algorithm at 100ns a pop, or if you're in code dealing with networks (routinely micro seconds, even within datacenters; milli seconds if you have to leave), or files, or anything else like that, micro-optimizing defers is not going to have any visible results to your speed but can very badly damage your code's correctness and ease of writing and modifying.

The other thing to know about defers is that they are not declarations, they are instructions; every time the program counter moves past one, another defer call is added to the stack of calls to make while exiting the function. So you do have to be careful about deferring in a loop, not so much because it's "dangerous" but just because it's easy to be unaware that the defers are not declarations. If you intend to do it, it's fine, it can just bite you if you do it accidentally.

[1]: https://gist.github.com/jboner/2841832

He does not have a firm grasp on testing/B. The package is reporting timings for b.N loops ("ops"). There is no need for yet another loop.

This is typical: https://github.com/cornelk/go-benchmark/blob/master/defer_te...

Defer also runs in the case of a panic. So it's not just a hidden goto.
more detail on why `defer` can/is more expensive (and not equivalent) to unrolling it: https://blog.golang.org/defer-panic-and-recover
Thanks, that is what I was looking for. I used defer just as convenience and wasn't aware (anymore) that it does something different than just pushing the function call to the end. Maybe it's time to take the Golang tour again ;-)
Defer is for reclaiming resources, or other cleanup at the end of a function which cannot otherwise be handled by the language, and (usually?) this is not going to be in your hot path; for example opening and closing a file many many times is not really a good thing to do anyway.