Replace SimpleRandom with (Simple)ThreadUnsafeRandom

ThreadUnsafeRandom is a random implementation that is
identical to LegacyRandomSource behaviourally, but
without the thread checks.

SimpleThreadUnsafeRandom is ThreadUnsafeRandom except with
its nextInt(int) function replaced with a faster
but more biased implementation when bound is very large.

Additionally, replace Level/Entity randoms with ThreadUnsafeRandom.
This avoids the expensive CAS logic at the expense of losing the
thread check.
This commit is contained in:
Spottedleaf
2024-11-27 06:16:27 -08:00
parent 0cfa6aa89a
commit f9b1c374e4
2 changed files with 294 additions and 36 deletions

View File

@@ -4037,36 +4037,41 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ private MoonriseConstants() {}
+
+}
diff --git a/src/main/java/ca/spottedleaf/moonrise/common/util/SimpleRandom.java b/src/main/java/ca/spottedleaf/moonrise/common/util/SimpleRandom.java
diff --git a/src/main/java/ca/spottedleaf/moonrise/common/util/SimpleThreadUnsafeRandom.java b/src/main/java/ca/spottedleaf/moonrise/common/util/SimpleThreadUnsafeRandom.java
new file mode 100644
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
--- /dev/null
+++ b/src/main/java/ca/spottedleaf/moonrise/common/util/SimpleRandom.java
+++ b/src/main/java/ca/spottedleaf/moonrise/common/util/SimpleThreadUnsafeRandom.java
@@ -0,0 +0,0 @@
+package ca.spottedleaf.moonrise.common.util;
+
+import net.minecraft.world.level.levelgen.LegacyRandomSource;
+import net.minecraft.util.Mth;
+import net.minecraft.util.RandomSource;
+import net.minecraft.world.level.levelgen.BitRandomSource;
+import net.minecraft.world.level.levelgen.MarsagliaPolarGaussian;
+import net.minecraft.world.level.levelgen.PositionalRandomFactory;
+
+/**
+ * Avoid costly CAS of superclass
+ * Avoid costly CAS of superclass + division in nextInt
+ */
+public final class SimpleRandom extends LegacyRandomSource {
+public final class SimpleThreadUnsafeRandom implements BitRandomSource {
+
+ private static final long MULTIPLIER = 25214903917L;
+ private static final long ADDEND = 11L;
+ private static final int BITS = 48;
+ private static final long MASK = (1L << BITS) - 1;
+ private static final long MASK = (1L << BITS) - 1L;
+
+ private long value;
+ private final MarsagliaPolarGaussian gaussianSource = new MarsagliaPolarGaussian(this);
+
+ public SimpleRandom(final long seed) {
+ super(0L);
+ this.value = seed;
+ public SimpleThreadUnsafeRandom(final long seed) {
+ this.setSeed(seed);
+ }
+
+ @Override
+ public void setSeed(final long seed) {
+ this.value = (seed ^ MULTIPLIER) & MASK;
+ this.gaussianSource.reset();
+ }
+
+ private long advanceSeed() {
@@ -4094,6 +4099,154 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ final long value = this.advanceSeed() >>> (BITS - Integer.SIZE);
+ return (int)((value * (long)bound) >>> Integer.SIZE);
+ }
+
+ @Override
+ public double nextGaussian() {
+ return this.gaussianSource.nextGaussian();
+ }
+
+ @Override
+ public RandomSource fork() {
+ return new SimpleThreadUnsafeRandom(this.nextLong());
+ }
+
+ @Override
+ public PositionalRandomFactory forkPositional() {
+ return new SimpleRandomPositionalFactory(this.nextLong());
+ }
+
+ public static final class SimpleRandomPositionalFactory implements PositionalRandomFactory {
+
+ private final long seed;
+
+ public SimpleRandomPositionalFactory(final long seed) {
+ this.seed = seed;
+ }
+
+ public long getSeed() {
+ return this.seed;
+ }
+
+ @Override
+ public RandomSource fromHashOf(final String string) {
+ return new SimpleThreadUnsafeRandom((long)string.hashCode() ^ this.seed);
+ }
+
+ @Override
+ public RandomSource fromSeed(final long seed) {
+ return new SimpleThreadUnsafeRandom(seed);
+ }
+
+ @Override
+ public RandomSource at(final int x, final int y, final int z) {
+ return new SimpleThreadUnsafeRandom(Mth.getSeed(x, y, z) ^ this.seed);
+ }
+
+ @Override
+ public void parityConfigString(final StringBuilder stringBuilder) {
+ stringBuilder.append("SimpleRandomPositionalFactory{").append(this.seed).append('}');
+ }
+ }
+}
diff --git a/src/main/java/ca/spottedleaf/moonrise/common/util/ThreadUnsafeRandom.java b/src/main/java/ca/spottedleaf/moonrise/common/util/ThreadUnsafeRandom.java
new file mode 100644
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
--- /dev/null
+++ b/src/main/java/ca/spottedleaf/moonrise/common/util/ThreadUnsafeRandom.java
@@ -0,0 +0,0 @@
+package ca.spottedleaf.moonrise.common.util;
+
+import net.minecraft.util.Mth;
+import net.minecraft.util.RandomSource;
+import net.minecraft.world.level.levelgen.BitRandomSource;
+import net.minecraft.world.level.levelgen.MarsagliaPolarGaussian;
+import net.minecraft.world.level.levelgen.PositionalRandomFactory;
+
+/**
+ * Avoid costly CAS of superclass
+ */
+public final class ThreadUnsafeRandom implements BitRandomSource {
+
+ private static final long MULTIPLIER = 25214903917L;
+ private static final long ADDEND = 11L;
+ private static final int BITS = 48;
+ private static final long MASK = (1L << BITS) - 1L;
+
+ private long value;
+ private final MarsagliaPolarGaussian gaussianSource = new MarsagliaPolarGaussian(this);
+
+ public ThreadUnsafeRandom(final long seed) {
+ this.setSeed(seed);
+ }
+
+ @Override
+ public void setSeed(final long seed) {
+ this.value = (seed ^ MULTIPLIER) & MASK;
+ this.gaussianSource.reset();
+ }
+
+ private long advanceSeed() {
+ return this.value = ((this.value * MULTIPLIER) + ADDEND) & MASK;
+ }
+
+ @Override
+ public int next(final int bits) {
+ return (int)(this.advanceSeed() >>> (BITS - bits));
+ }
+
+ @Override
+ public int nextInt() {
+ final long seed = this.advanceSeed();
+ return (int)(seed >>> (BITS - Integer.SIZE));
+ }
+
+ @Override
+ public double nextGaussian() {
+ return this.gaussianSource.nextGaussian();
+ }
+
+ @Override
+ public RandomSource fork() {
+ return new ThreadUnsafeRandom(this.nextLong());
+ }
+
+ @Override
+ public PositionalRandomFactory forkPositional() {
+ return new ThreadUnsafeRandomPositionalFactory(this.nextLong());
+ }
+
+ public static final class ThreadUnsafeRandomPositionalFactory implements PositionalRandomFactory {
+
+ private final long seed;
+
+ public ThreadUnsafeRandomPositionalFactory(final long seed) {
+ this.seed = seed;
+ }
+
+ public long getSeed() {
+ return this.seed;
+ }
+
+ @Override
+ public RandomSource fromHashOf(final String string) {
+ return new ThreadUnsafeRandom((long)string.hashCode() ^ this.seed);
+ }
+
+ @Override
+ public RandomSource fromSeed(final long seed) {
+ return new ThreadUnsafeRandom(seed);
+ }
+
+ @Override
+ public RandomSource at(final int x, final int y, final int z) {
+ return new ThreadUnsafeRandom(Mth.getSeed(x, y, z) ^ this.seed);
+ }
+
+ @Override
+ public void parityConfigString(final StringBuilder stringBuilder) {
+ stringBuilder.append("ThreadUnsafeRandomPositionalFactory{").append(this.seed).append('}');
+ }
+ }
+}
diff --git a/src/main/java/ca/spottedleaf/moonrise/common/util/TickThread.java b/src/main/java/ca/spottedleaf/moonrise/common/util/TickThread.java
new file mode 100644