What's new

What is faster: bit operations or if statements?

thesteelydane

Bunker Samples
I’ve seen a bit (pun intended) of code that used bit operations to make sure a value didn’t exceed a certain threshold, basically using sh_right(value,31) and some math.
I can accomplish the same with a simple If statement:


Code:
if (value >= threshold)
      value := threshold
end if

So why use sh_right instead? Said piece of code was being called inside a busy listener callback, but is it really that much more efficient than an if statement?
 
Last edited:
I don't use and know nothing about KSP, but in other languages there's a clamp() function for things like that, which I find more readable than a bit shift and also is just one line.
 
Native bit-shifts are super fast (normally only one cycle for the calculation). Compared to that simple if checks with bigger or smaller require around 3 cycles. Comparisons with smaller-equals (<=) or bigger-equals (>=) are also more expensive need additional 1-2 cycles.

As mentioned this all is true for native code (assembly, C, C++). If you are using another language you should check how the compiler/interpreter handles these instructions.
Many script languages are not capable of true bit-operations, which makes these operations really expensive during run-time. In this case a simple "if" is not only more readable but performs better as well.
 
Well, I have a double sequencer running in a very busy listener callback, and after I replaced my if statement with sh_right and some math, CPU usage went from 2% to 1 %, so there is a noticeable difference! I don't think my sequencers can be more efficient than they are now, so I'm happy I discovered this trick!
 
Last edited:
Sure! Say you have a value that you want to keep between 0 and a max. So if its less than 0 you want it to be 0 and if its more than max, you want it to be max, you can do something like this:

Code:
result := value*(1+(sh_right(max-value, 31) .or. sh_right(value, 31)))-(max * sh_right(max-value, 31))
 
Thanks! That's remarkable. But with the three bitshifts, the .or. comparison, a subtraction, an addition, and two multiplications ... all that is still computationally more efficient than >= ?
 
Bit shifts and binary comparisons are superfast operations.

Whenever you have a branch, the CPU usually guesses what might happen, but if it guesses wrongly, you end up with slower code execution because it needs to trace things back, reload different data into registers, and so on. Oftentimes this ends up being longer than three bitshifts, binary OR, and a few adds/multiplies. :)

 
Thanks! That's remarkable. But with the three bitshifts, the .or. comparison, a subtraction, an addition, and two multiplications ... all that is still computationally more efficient than >= ?

I don't even understand how bit shifts work, I just know what they spit out. In this case I replaced an if statement in a listener callback with this line of code, and my CPU usage dropped from 2 to 1 %, so it would seem so....

This is all anecdotal evidence of course, I have no hard data to back it up.
 
Last edited:
It's useful in some cases, but as a must-have optimization, I think you shouldn't look at it like that. Bitshifting is useful when working with bitmasks, for example.
 
  • Like
Reactions: ism
Bitmasks have semantic value in a language as primitive as KSP. And premature optimization is one if the great sins of engineering.


I’m just learning KSP myself and surprised that this kind of register level optimization is even contemplated in such an high level, abstracted scripting language. Even a 1% performance increase seems quite shocking.
 
Last edited:
Again I don't think these commands should be looked at through the prism of optimization. You can do nifty stuff with bitwise operations...
 
It's probably unnecessary for KSP optimisation generally. But I DO use a lot of clamping in some of my scripts, so much so that it's almost always a called function. If that function is slightly improved, it certainly doesn't hurt to use that instead.

Plus I'm curious about the bitshift logic... it's slightly tricky to get my head around. ;)
 
Bitshifts are fast multiplies or divisions. Divisions are more CPU expensive than bitshifts. Single bitshift left is multiply by 2, single bitshift right is divide by 2.
 
It's probably unnecessary for KSP optimisation generally. But I DO use a lot of clamping in some of my scripts, so much so that it's almost always a called function. If that function is slightly improved, it certainly doesn't hurt to use that instead.

Plus I'm curious about the bitshift logic... it's slightly tricky to get my head around. ;)

It’s a head scratcher for sure, and I suck at math, so took a while for me to get my head around. By the way, if you only need to make sure your value doesn’t get over the max, you can get rid of the .or. and the second sh_right in the example above.
 
Top Bottom