I have the following code in one of my projects that chooses a unit for a given memory amount. I think that MiB is less likely than GiB, so I used a branch hint.
const mem,
const unit: *const [3]u8
= mem: {
if (kibibytes < 1 << 20) {
@branchHint(.unlikely);
break :mem .{kibibytes / (1 << 10), "MiB"};
}
break :mem .{kibibytes / (1 << 20), "GiB"};
};
My question is, would the following code do the same thing or result in different machine code?
const mem,
const unit: *const [3]u8
= mem: {
if (kibibytes < 1 << 20) {
@branchHint(.unlikely);
break :mem .{kibibytes / (1 << 10), "MiB"};
}
else {
@branchHint(.likely);
break :mem .{kibibytes / (1 << 20), "GiB"};
}
};
Which of these two is better? Does it even matter?
As far as I know, they are identical. I would say the first one is more readable, but if you really wanted to, you could just make it an else branch. The @branchHint(.likely)
is unnecessary.
1 Like
godbolt is the tool of choice if you want answers to questions about machine code.
As you can see on godbolt they do produce the same code (so much so that I had to alter the strings in one of them to prevent the compile from just making them use the same function).
3 Likes
Thanks for the advice on using Godbolt, I will do that in the future. Since they produce the same machine code, I will opt for the first one because I think it’s more readable.
If you have to ask - never!
To be more informative, you would use it if you are looking at generated machine code, and you are observing that it orders the jump destinations backwards from how you want them to be ordered.
Much like inline
, @branchHint
is a part of the language that seems like a tasty treat to beginners to sprinkle everywhere, but it’s actually better to almost never use it unless you have actually run into a problem that it solves.
As a rule of thumb, every @branchHint
should have a comment linking to a benchmark script that you ran, demonstrating that it makes a difference. Otherwise there’s no point, and you’re only fantasizing about performance characteristics that don’t exist.
I strongly recommend everyone to never use @branchHint
. Those who actually need to use it, already know when to ignore this advice.
16 Likes
Thanks for the response. I’m also guilty of using inline everywhere xD. I’ll follow your advice and not use them unless I have a reason to.
I too have been guilty of optimization without prior benchmarks. Just last week I found that removing one inline
from my code resulted in a 7% perf boost.
1 Like
Inlining is the one of the most if not the most valuable optimizations that compiler can perform, because inlined code allows to optimise inlined code with it’s caller context, but inlines are double edged sword, because they also produce more machine code hence increase cache misses.
If I remember correctly, cpp has fun story about inline keyword, because originally it was an optimizer hint for inlining and now it has only semantic meaning and does not affect actual inline optimization at all xD