package be.vandewalleh.aoc.days import java.util.concurrent.TimeUnit import kotlin.math.pow import org.openjdk.jmh.annotations.* import org.openjdk.jmh.infra.Blackhole import org.openjdk.jmh.runner.Runner import org.openjdk.jmh.runner.options.Options import org.openjdk.jmh.runner.options.OptionsBuilder /* Benchmark Mode Cnt Score Error Units Day14Benchmark.charArrays avgt 5 0.038 ± 0.001 ms/op Day14Benchmark.countReplacePad avgt 5 0.044 ± 0.002 ms/op Day14Benchmark.stringBuilders avgt 5 0.082 ± 0.005 ms/op */ @BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.MILLISECONDS) @State(Scope.Benchmark) @Warmup(iterations = 3) @Measurement(iterations = 5) open class Day14Benchmark { private val mask = "1XX10X10100X1010X1000100X0X10X001X00" private val address = 43398.toString(2).padStart(36, '0') @Benchmark fun stringBuilders(blackhole: Blackhole) { val mutationCount = mask.count { it == 'X' }.let { 2.0.pow(it.toDouble()).toInt() } val mutations = Array(mutationCount) { StringBuilder(36) } var groups = 1 for (i in mask.indices) { when (mask[i]) { 'X' -> { groups *= 2 val groupSize = mutationCount / groups var currentChar = '1' for (b in mutations.indices) { val builder = mutations[b] val flip = b % groupSize == 0 if (flip) currentChar = if (currentChar == '0') '1' else '0' builder.append(currentChar) } } '1' -> mutations.forEach { it.append('1') } else -> mutations.forEach { it.append(address[i]) } } } blackhole.consume(mutations) } @Benchmark fun charArrays(blackhole: Blackhole) { val mutationCount = mask.count { it == 'X' }.let { 2.0.pow(it.toDouble()).toInt() } val mutations = Array(mutationCount) { CharArray(36) } var groups = 1 for (i in mask.indices) { when (mask[i]) { 'X' -> { groups *= 2 val groupSize = mutationCount / groups var currentChar = '1' for (b in mutations.indices) { val builder = mutations[b] val flip = b % groupSize == 0 if (flip) currentChar = if (currentChar == '0') '1' else '0' builder[i] = currentChar } } '1' -> mutations.forEach { it[i] = '1' } else -> mutations.forEach { it[i] = address[i] } } } blackhole.consume(mutations) } @Benchmark fun countReplacePad(blackhole: Blackhole) { val bitCount = mask.count { it == 'X' } val mutationCount = bitCount.let { 2.0.pow(it.toDouble()).toInt() } val results = Array(mutationCount) { CharArray(36) } repeat(mutationCount) { i -> var count = 0 val result = results[i] val currentMask = i.toString(2).padStart(bitCount, '0') for (j in address.indices) { result[j] = when (mask[j]) { 'X' -> currentMask[count++] '1' -> '1' else -> address[j] } } } blackhole.consume(results) } } fun main() { val opt: Options = OptionsBuilder() .include(Day14Benchmark::class.java.simpleName) .forks(1) .build() Runner(opt).run() }