Skip to content

Commit

Permalink
Refactor isPressed method in KeyUtils
Browse files Browse the repository at this point in the history
remove imperatively avoid using streams when the input has only one element, according to benchmark
  • Loading branch information
boholder committed Nov 11, 2023
1 parent 758f3b3 commit 2ce825b
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 13 deletions.
4 changes: 4 additions & 0 deletions common/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ dependencies {
testImplementation "org.assertj:assertj-core:3.24.2"
testImplementation "org.mockito:mockito-core:5.4.0"
testImplementation "org.mockito:mockito-junit-jupiter:5.4.0"

// benchmark dependencies
testImplementation "org.openjdk.jmh:jmh-core:1.37"
testAnnotationProcessor "org.openjdk.jmh:jmh-generator-annprocess:1.37"
}

test {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,7 @@ public static boolean isAnyPressed(int... keyCodes) {
MinecraftClient minecraftClient = MinecraftClient.getInstance();
if (minecraftClient == null) return false;
long handle = minecraftClient.getWindow().getHandle();
if (keyCodes.length == 1) {
return InputUtil.isKeyPressed(handle, keyCodes[0]);
} else {
return IntStream.of(keyCodes).anyMatch(c -> InputUtil.isKeyPressed(handle, c));
}
return IntStream.of(keyCodes).anyMatch(c -> InputUtil.isKeyPressed(handle, c));
}

public static boolean isAllPressed(int... keyCodes) {
Expand All @@ -40,14 +36,10 @@ public static boolean isAllPressed(int... keyCodes) {
* Get these instances via InputUtil.fromTranslationKey({key})
*/
public static boolean isAnyPressed(KeyBinding... keyBindings) {
if (keyBindings.length == 1) {
return isAnyPressed(InputUtil.fromTranslationKey(keyBindings[0].getBoundKeyTranslationKey()).getCode());
} else {
int[] array = Arrays.stream(keyBindings)
.mapToInt(b -> InputUtil.fromTranslationKey(b.getBoundKeyTranslationKey()).getCode())
.toArray();
return isAnyPressed(array);
}
int[] array = Arrays.stream(keyBindings)
.mapToInt(b -> InputUtil.fromTranslationKey(b.getBoundKeyTranslationKey()).getCode())
.toArray();
return isAnyPressed(array);
}

@SuppressWarnings("unused")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package com.github.khanshoaib3.minecraft_access.benchmarks;

import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.OutputTimeUnit;

import java.util.concurrent.TimeUnit;
import java.util.stream.IntStream;

/**
* Should I imperatively avoid using streams when the input has only one element for checking key is pressed?
* <p>
* result:
* Benchmark Mode Cnt Score Error Units
* OptimizeForCheckingKeyIsPressed.notUseStreamForOneElement avgt 25 0.471 ± 0.004 ns/op
* OptimizeForCheckingKeyIsPressed.useStreamForOneElement avgt 25 18.463 ± 0.146 ns/op
* <p>
* 18 nanos diff, quite a small difference,
* there are about 60 invokes on this method,
* 18 * 60 = 1080 nanos = 0.001 millis
* One tick is 50 millis, so the diff takes a very small part of one tick.
* Conclusion: I should not avoid using streams.
* <p>
* ref:
* There aren't big general speed differences between streams and loops: <a href="https://stackoverflow.com/a/34632749/11397457">...</a>
* <a href="https://minecraft.fandom.com/wiki/Tick">...</a>
*/
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public class OptimizeForCheckingKeyIsPressed {
private static final int[] keyCode = new int[]{0};

public static void main(String[] args) throws Exception {
org.openjdk.jmh.Main.main(args);
}

@Benchmark
public boolean useStreamForOneElement() {
int handle = 1;
return IntStream.of(keyCode).anyMatch(c -> mockIsKeyPressed(handle, c));
}

@Benchmark
public boolean notUseStreamForOneElement() {
int handle = 1;
return mockIsKeyPressed(handle, keyCode[0]);
}

private static boolean mockIsKeyPressed(int handle, int code) {
return handle > code;
}
}

0 comments on commit 2ce825b

Please sign in to comment.