diff --git a/sources/src/main/java/io/akarin/server/core/AkarinGlobalConfig.java b/sources/src/main/java/io/akarin/server/core/AkarinGlobalConfig.java index 2d64c651f..4abecb100 100644 --- a/sources/src/main/java/io/akarin/server/core/AkarinGlobalConfig.java +++ b/sources/src/main/java/io/akarin/server/core/AkarinGlobalConfig.java @@ -160,6 +160,11 @@ public class AkarinGlobalConfig { playersPerIOThread = getInt("core.players-per-chunk-io-thread", 50); } + public static boolean silentAsyncTimings; + private static void silentAsyncTimings() { + silentAsyncTimings = getBoolean("core.always-silent-async-timing", false); + } + public static long timeUpdateInterval; private static void timeUpdateInterval() { timeUpdateInterval = getSeconds(getString("core.tick-rate.world-time-update-interval", "1s")) * 10; diff --git a/sources/src/main/java/io/akarin/server/mixin/core/MixinTimingHandler.java b/sources/src/main/java/io/akarin/server/mixin/core/MixinTimingHandler.java index 1904c966f..2ac2a059e 100644 --- a/sources/src/main/java/io/akarin/server/mixin/core/MixinTimingHandler.java +++ b/sources/src/main/java/io/akarin/server/mixin/core/MixinTimingHandler.java @@ -9,8 +9,13 @@ import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + import co.aikar.timings.Timing; import io.akarin.api.internal.Akari; +import io.akarin.api.internal.Akari.AssignableThread; import io.akarin.server.core.AkarinGlobalConfig; import net.minecraft.server.MinecraftServer; @@ -24,12 +29,18 @@ public abstract class MixinTimingHandler { @Shadow abstract void addDiff(long diff); @Shadow public abstract Timing startTiming(); - @Overwrite + @Overwrite // Overwrite to avoid twice thread check public Timing startTimingIfSync() { startTiming(); return (Timing) this; } + @SuppressWarnings({"rawtypes", "unchecked"}) + @Inject(method = "startTiming", at = @At("HEAD"), cancellable = true) + public void onStartTiming(CallbackInfoReturnable ci) { + if (!Akari.isPrimaryThread(false)) ci.setReturnValue(this); // Avoid modify any field + } + @Overwrite public void stopTimingIfSync() { if (Akari.isPrimaryThread(false)) { @@ -47,17 +58,21 @@ public abstract class MixinTimingHandler { } public void stopTiming(boolean alreadySync) { - if (!enabled || --timingDepth != 0 || start == 0) return; + if (!enabled) return; if (!alreadySync) { Thread curThread = Thread.currentThread(); + if (curThread.getClass() == AssignableThread.class) return; if (curThread != MinecraftServer.getServer().primaryThread) { - start = 0; - return; + if (AkarinGlobalConfig.silentAsyncTimings) return; + Bukkit.getLogger().log(Level.SEVERE, "stopTiming called async for " + name); + Thread.dumpStack(); } } - // Safety ensured - addDiff(System.nanoTime() - start); - start = 0; + // Main thread ensured + if (--timingDepth == 0 && start != 0) { + addDiff(System.nanoTime() - start); + start = 0; + } } }