martmists
12/15/2022, 1:55 PMfun Pair<Int, Int>.sumIsEven() = (first xor second) and 1 == 0
fun Pair<Int, Int>.sumIsEvenAlt() = (first + second) % 2 == 0
I would assume the former to be faster as it doesn't require summing and dividing and just does bitwise comparisons, but I'm getting the following results:
=== Case 1 ===
Average: 42ns
Max: 546_802ns
Total: 42_349_933ns
=== Case 2 ===
Average: 36ns
Max: 52_984ns
Total: 36_907_022ns
What's the reason for this difference?Sergei Petunin
12/15/2022, 2:08 PMmartmists
12/15/2022, 2:18 PMPaul Griffith
12/15/2022, 3:37 PMGleb Minaev
12/15/2022, 5:54 PMInt
argument and with single Pair<Int, Int>
argument. Here is the result:
Mathematical, not boxed:
3,865 ±(99.9%) 0,151 ns/op
Bitwise, not boxed:
3,788 ±(99.9%) 0,016 ns/op
Mathematical, boxed:
4,087 ±(99.9%) 0,182 ns/op
Bitwise, boxed:
4,061 ±(99.9%) 0,012 ns/op
The results shows that there is no significant difference. The bitwise alternative is just slightly faster and more time-stable.
P.S. The benchmark code:
@State(Scope.Thread)
open class OperationsBenchmark {
var first: Int = 575757
var second: Int = 179179
@Setup(Level.Iteration)
fun prepareValues() {
first = Random.nextInt()
second = Random.nextInt()
}
@Benchmark
fun Blackhole.mathematicalIsEven() {
consume((first + second) % 2 == 0)
}
@Benchmark
fun Blackhole.bitwiseIsEven() {
consume((first xor second) and 1 == 0)
}
}
@State(Scope.Thread)
open class BoxedOperationsBenchmark {
var inputBox: Pair<Int, Int> = Pair(575757, 179179)
@Setup(Level.Iteration)
fun prepareValues() {
inputBox = Pair(Random.nextInt(), Random.nextInt())
}
@Benchmark
fun Blackhole.mathematicalIsEven() {
consume((inputBox.first + inputBox.second) % 2 == 0)
}
@Benchmark
fun Blackhole.bitwiseIsEven() {
consume((inputBox.first xor inputBox.second) and 1 == 0)
}
}
And the benchmark configuration:
warmups = 20
iterations = 10
iterationTime = 3
mode = "avgt"
outputTimeUnit = "ns"
Paul Griffith
12/15/2022, 7:09 PM