From f685dd4c4c3ff31484afe4899074a52c1c26ba91 Mon Sep 17 00:00:00 2001 From: AnOpenSauceDev <119765865+AnOpenSauceDev@users.noreply.github.com> Date: Fri, 26 Apr 2024 17:18:30 +1000 Subject: [PATCH] create api --- README.md | 5 +- .../fasterrandom/FasterRandom.java | 10 +- .../fasterrandom/FasterRandomPreLaunch.java | 2 +- .../RandomNumberGenerationBenchmark.java | 151 ------------------ .../fasterrandom/mixin/RandomMixin.java | 28 ---- 5 files changed, 5 insertions(+), 191 deletions(-) delete mode 100644 src/main/java/com/github/anopensaucedev/fasterrandom/benchmark/RandomNumberGenerationBenchmark.java delete mode 100644 src/main/java/com/github/anopensaucedev/fasterrandom/mixin/RandomMixin.java diff --git a/README.md b/README.md index eb9fa49..3ca2e71 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,6 @@ -# FastRandom -Source Code and issues for [Faster Random](https://modrinth.com/mod/faster-random) +# Faster Random: API + +A drop-in replacement for using Minecraft's `Random` class, instead taking advantage of Faster Random's 8X faster number generator. Requires a JVM that supports `RandomGenerator` and the LXM generators. Some JRE's don't support this. diff --git a/src/main/java/com/github/anopensaucedev/fasterrandom/FasterRandom.java b/src/main/java/com/github/anopensaucedev/fasterrandom/FasterRandom.java index 40d1da2..b75f426 100644 --- a/src/main/java/com/github/anopensaucedev/fasterrandom/FasterRandom.java +++ b/src/main/java/com/github/anopensaucedev/fasterrandom/FasterRandom.java @@ -21,15 +21,7 @@ public class FasterRandom implements ModInitializer { @Override public void onInitialize() { - LOGGER.info("{} v{} has loaded! \\0_0/", MOD_NAME, MOD_VERSION); - LOGGER.info( - "If you have any terrain-related problems, open an issue on the issue tracker. Make sure to mention me (AnOpenSauceDev) in the issue just to be sure!"); - LOGGER.info("Faster Random issue tracker: https://github.com/AnOpenSauceDev/FastRandom/issues"); + LOGGER.info("{}-API v{} has loaded! \\0_0/", MOD_NAME, MOD_VERSION); - // Run random benchmarks if the mod is running in a development environment - if (FabricLoader.getInstance().isDevelopmentEnvironment()) { - RandomNumberGenerationBenchmark.runLegacyBenchmark(); - RandomNumberGenerationBenchmark.runBenchmark(); - } } } diff --git a/src/main/java/com/github/anopensaucedev/fasterrandom/FasterRandomPreLaunch.java b/src/main/java/com/github/anopensaucedev/fasterrandom/FasterRandomPreLaunch.java index 4385098..6fee22e 100644 --- a/src/main/java/com/github/anopensaucedev/fasterrandom/FasterRandomPreLaunch.java +++ b/src/main/java/com/github/anopensaucedev/fasterrandom/FasterRandomPreLaunch.java @@ -9,7 +9,7 @@ public class FasterRandomPreLaunch implements PreLaunchEntrypoint { @Override public void onPreLaunch() { - LOGGER.info("Preparing to launch Faster Random!"); + LOGGER.info("Preparing to launch Faster Random-API!"); LOGGER.info("If Minecraft crashes past this point, your JVM is not supported."); FasterRandom.RANDOM_GENERATOR_FACTORY.create(); LOGGER.info("Your JVM seems to be supported!"); diff --git a/src/main/java/com/github/anopensaucedev/fasterrandom/benchmark/RandomNumberGenerationBenchmark.java b/src/main/java/com/github/anopensaucedev/fasterrandom/benchmark/RandomNumberGenerationBenchmark.java deleted file mode 100644 index dfb77d5..0000000 --- a/src/main/java/com/github/anopensaucedev/fasterrandom/benchmark/RandomNumberGenerationBenchmark.java +++ /dev/null @@ -1,151 +0,0 @@ -package com.github.anopensaucedev.fasterrandom.benchmark; - -import com.github.anopensaucedev.fasterrandom.FasterRandom; -import net.minecraft.util.math.random.CheckedRandom; -import net.minecraft.util.math.random.RandomSeed; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Random; -import java.util.concurrent.ThreadLocalRandom; - -/** - * A benchmarking tool for various random number generators. - */ -public class RandomNumberGenerationBenchmark { - private static final Logger BENCHMARK_LOGGER = LoggerFactory.getLogger("Faster Random RandomNumberGenerationBenchmark"); - /** - * Minecraft's vanilla random number generator. - */ - private static final CheckedRandom VANILLA_RANDOM = new CheckedRandom(RandomSeed.getSeed()); - /** - * Legacy {@link Random} from {@link java.util}. - */ - private static final Random OLD_RANDOM = new Random(RandomSeed.getSeed()); - /** - * An ordered list of random number generator names. - */ - private static final String[] GENERATOR_NAMES = {"vanilla", "java.util.random", "ThreadLocalRandom", "LXM"}; - /** - * The amount of iterations the benchmark runs. - */ - private static final int ITERATIONS = 100_000_000; // Stress testing! Lower when actual development needs to happen - /** - * The timing values of the tested random number generators. - */ - private static final ArrayList TIMING_VALUES = new ArrayList<>(); - - /** - * Runs a benchmark of various random number generators. - * Can be slow (and thus impact loading times if ran on game start). - */ - public static void runBenchmark() { - BENCHMARK_LOGGER.info("Starting Random benchmark!"); - - // Vanilla random - BENCHMARK_LOGGER.info("Vanilla benchmark"); - var vanillaStart = System.nanoTime(); - for (int i = 0; i < ITERATIONS; i++) { - VANILLA_RANDOM.nextFloat(); - VANILLA_RANDOM.nextInt(); - VANILLA_RANDOM.nextDouble(); - VANILLA_RANDOM.nextGaussian(); - VANILLA_RANDOM.nextLong(); - VANILLA_RANDOM.nextBoolean(); - } - var vanillaFinish = toSeconds(System.nanoTime() - vanillaStart); - BENCHMARK_LOGGER.info("Vanilla benchmark time: {}s, mean: {}s", vanillaFinish, (float) (vanillaFinish / ITERATIONS)); - TIMING_VALUES.add(vanillaFinish); //0 - - // Java.util.random - BENCHMARK_LOGGER.info("java.util.random"); - var oldRandomStart = System.nanoTime(); - for (int i = 0; i < ITERATIONS; i++) { - OLD_RANDOM.nextFloat(); - OLD_RANDOM.nextInt(); - OLD_RANDOM.nextDouble(); - OLD_RANDOM.nextGaussian(); - OLD_RANDOM.nextLong(); - OLD_RANDOM.nextBoolean(); - } - var oldRandomFinish = toSeconds(System.nanoTime() - oldRandomStart); - BENCHMARK_LOGGER.info("java.util.random time: {}s, mean: {}s", oldRandomFinish, (float) (oldRandomFinish / ITERATIONS)); - TIMING_VALUES.add(oldRandomFinish); //1 - - // ThreadLocalRandom ("100X faster" than the old CheckedRandom) - // TODO: Add old CheckedRandom implementation as a benchmark alongside the existing benchmarks - BENCHMARK_LOGGER.info("ThreadLocalRandom"); - var threadLocalRandom = ThreadLocalRandom.current(); - var threadLocalStart = System.nanoTime(); - for (int i = 0; i < ITERATIONS; i++) { - threadLocalRandom.nextFloat(); - threadLocalRandom.nextInt(); - threadLocalRandom.nextDouble(); - threadLocalRandom.nextGaussian(); - threadLocalRandom.nextLong(); - threadLocalRandom.nextBoolean(); - } - var threadLocalFinish = toSeconds(System.nanoTime() - threadLocalStart); - BENCHMARK_LOGGER.info("ThreadLocalRandom time: {}s, mean: {}s", threadLocalFinish, (float) (threadLocalFinish / ITERATIONS)); - TIMING_VALUES.add(threadLocalFinish); // 2 - - // LXM random - BENCHMARK_LOGGER.info("LXM"); - var generator = FasterRandom.RANDOM_GENERATOR_FACTORY.create(); - var lxmStart = System.nanoTime(); - for (int i = 0; i < ITERATIONS; i++) { - generator.nextFloat(); - generator.nextInt(); - generator.nextDouble(); - generator.nextGaussian(); - generator.nextLong(); - generator.nextBoolean(); - } - var lxmFinish = toSeconds(System.nanoTime() - lxmStart); - BENCHMARK_LOGGER.info("LXM time: {}s, mean: {}s", lxmFinish, (float) (lxmFinish / ITERATIONS)); - TIMING_VALUES.add(lxmFinish); // 3 - - BENCHMARK_LOGGER.info("Overall winner: {}s, from random generator: {}", Collections.min(TIMING_VALUES), - GENERATOR_NAMES[TIMING_VALUES.indexOf(Collections.min(TIMING_VALUES))] - ); - } - - /** - * Runs a legacy benchmark of various random number generators. - * Can be slow (and thus impact loading times if ran on game start). - * This is an older benchmark from Methane, where {@link CheckedRandom} is 100x slower on average than {@link ThreadLocalRandom}. - */ - public static void runLegacyBenchmark() { - int iterations = 1000000000; - ThreadLocalRandom random = ThreadLocalRandom.current(); - long time = System.nanoTime(); - for (int x = 0; x < iterations; x++) { - random.nextFloat(); - } - - long finalTime = System.nanoTime() - time; - BENCHMARK_LOGGER.info( - "Legacy Random Number Generation Benchmark (ThreadLocal): {}", RandomNumberGenerationBenchmark.toSeconds(finalTime)); - - // Seeded or not, this is always slower - net.minecraft.util.math.random.Random random2 = net.minecraft.util.math.random.Random.create(RandomSeed.getSeed()); - long time2 = System.nanoTime(); - for (int x = 0; x < iterations; x++) { - random2.nextFloat(); - } - - long finalTime2 = System.nanoTime() - time2; - BENCHMARK_LOGGER.info( - "Legacy Random Number Generation Benchmark (Random): {}", RandomNumberGenerationBenchmark.toSeconds(finalTime2)); - - if (finalTime < finalTime2) { - FasterRandom.LOGGER.info("ThreadLocal was faster!"); - } - } - - private static double toSeconds(double value) { - return (value / 1e9); - } -} diff --git a/src/main/java/com/github/anopensaucedev/fasterrandom/mixin/RandomMixin.java b/src/main/java/com/github/anopensaucedev/fasterrandom/mixin/RandomMixin.java deleted file mode 100644 index 4dc9f3c..0000000 --- a/src/main/java/com/github/anopensaucedev/fasterrandom/mixin/RandomMixin.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.github.anopensaucedev.fasterrandom.mixin; - -import com.github.anopensaucedev.fasterrandom.util.math.random.RandomGeneratorRandom; -import net.minecraft.util.math.random.Random; -import net.minecraft.util.math.random.RandomSeed; -import org.jetbrains.annotations.NotNull; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - -@Mixin(Random.class) -public interface RandomMixin { - @Inject(method = "create(J)Lnet/minecraft/util/math/random/Random;", at = @At(value = "HEAD"), cancellable = true) - private static void fasterrandom$createInject(long seed, @NotNull CallbackInfoReturnable cir) { - cir.setReturnValue(new RandomGeneratorRandom(seed)); - } - - @Inject(method = "createLocal", at = @At(value = "HEAD"), cancellable = true) - private static void fasterrandom$createLocalInject(@NotNull CallbackInfoReturnable cir) { - cir.setReturnValue(new RandomGeneratorRandom(RandomSeed.getSeed())); - } - - @Inject(method = "createThreadSafe", at = @At(value = "HEAD"), cancellable = true) - private static void fasterrandom$createThreadSafeInject(@NotNull CallbackInfoReturnable cir) { - cir.setReturnValue(new RandomGeneratorRandom(RandomSeed.getSeed())); - } -}