Skip to content

Commit 302bfaa

Browse files
committed
Add per-tick async profiler modes
1 parent 0ba86ae commit 302bfaa

File tree

5 files changed

+140
-18
lines changed

5 files changed

+140
-18
lines changed

build.gradle

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,13 @@ mixinGen {
8989
it.injectorsDefaultRequire = 1
9090
}
9191

92+
config(sourceSets.main, "debug") {
93+
it.required = false
94+
it.conformVisibility = true
95+
it.injectorsDefaultRequire = 0
96+
it.configurationPlugin = "io.github.opencubicchunks.cubicchunks.mixin.DebugMixinConfig"
97+
}
98+
9299
config(sourceSets.forge, "forge") {
93100
it.required = true
94101
it.conformVisibility = true
@@ -129,13 +136,6 @@ mixinGen {
129136
injectorsDefaultRequire = 1
130137
}
131138
132-
config("debug") {
133-
required = false
134-
conformVisibility = true
135-
injectorsDefaultRequire = 0
136-
configurationPlugin = "io.github.opencubicchunks.cubicchunks.mixin.DebugMixinConfig"
137-
}
138-
139139
config("test") {
140140
required = true
141141
conformVisibility = true
@@ -173,16 +173,8 @@ neoForge {
173173
"-Dmixin.debug.export=true",
174174
"-Dmixin.checks.interfaces=true",
175175
"-Dcubicchunks.debug=false",
176-
"-Dcubicchunks.debug.loadorder=false",
177-
"-Dcubicchunks.debug.window=false",
178-
"-Dcubicchunks.debug.statusrenderer=false",
179-
"-Dcubicchunks.debug.heightmaprenderer=false",
180-
"-Dcubicchunks.debug.heightmaprenderer.server=false",
181-
"-Dcubicchunks.debug.heightmaprenderer.render_lightmap=false",
182-
"-Dcubicchunks.debug.heightmaprenderer.radius=2",
183-
"-Dcubicchunks.debug.heightmapverification=false",
184-
"-Dcubicchunks.debug.heightmapverification.frequency=1",
185-
"-Dcubicchunks.debug.biomes=false",
176+
"-Dcubicchunks.debug.profiler=false",
177+
"-Dcubicchunks.debug.profiler.interval_ns=1",
186178
"-ea"
187179
]
188180
// applies to all the run configs below
@@ -273,6 +265,8 @@ dependencies {
273265
libraries("io.github.opencubicchunks:regionlib:0.63.0-SNAPSHOT")
274266
libraries("org.spongepowered:noise:2.0.0-SNAPSHOT")
275267

268+
libraries('tools.profiler:async-profiler:4.0')
269+
276270
testImplementation("org.assertj:assertj-core:3.25.1")
277271
testImplementation("org.junit.jupiter:junit-jupiter-api:5.10.0")
278272
testImplementation("org.junit.jupiter:junit-jupiter-params:5.10.0")
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package io.github.opencubicchunks.cubicchunks.mixin;
2+
3+
import java.util.List;
4+
import java.util.Set;
5+
6+
import org.objectweb.asm.tree.ClassNode;
7+
import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin;
8+
import org.spongepowered.asm.mixin.extensibility.IMixinInfo;
9+
10+
public class DebugMixinConfig implements IMixinConfigPlugin {
11+
private static final boolean DEBUG_MIXINS_ENABLED = System.getProperty("cubicchunks.debug", "false").equals("true");
12+
13+
@Override public void onLoad(String mixinPackage) {}
14+
15+
@Override public String getRefMapperConfig() {
16+
return null;
17+
}
18+
19+
@Override public boolean shouldApplyMixin(String targetClassName, String mixinClassName) {
20+
return DEBUG_MIXINS_ENABLED;
21+
}
22+
23+
@Override public void acceptTargets(Set<String> myTargets, Set<String> otherTargets) {}
24+
25+
@Override public List<String> getMixins() {
26+
return null;
27+
}
28+
29+
@Override public void preApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {}
30+
31+
@Override public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {}
32+
}
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
package io.github.opencubicchunks.cubicchunks.mixin.debug.common;
2+
3+
import java.io.IOException;
4+
import java.nio.file.Files;
5+
import java.nio.file.Path;
6+
import java.time.Duration;
7+
import java.util.function.BooleanSupplier;
8+
9+
import io.github.opencubicchunks.cubicchunks.CubicChunks;
10+
import net.minecraft.server.MinecraftServer;
11+
import one.profiler.AsyncProfiler;
12+
import org.apache.commons.io.FileUtils;
13+
import org.spongepowered.asm.mixin.Mixin;
14+
import org.spongepowered.asm.mixin.Unique;
15+
import org.spongepowered.asm.mixin.injection.At;
16+
import org.spongepowered.asm.mixin.injection.Inject;
17+
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
18+
19+
@Mixin(MinecraftServer.class)
20+
public class MixinMinecraftServer {
21+
@Unique private static final boolean perf_doProfiling = System.getProperty("cubicchunks.debug.profiler", "false").equals("true");
22+
23+
@Unique private static final Path perf_basePath = Path.of(System.getProperty("cubicchunks.debug.profiler.path", "profiler"));
24+
@Unique private static final int perf_interval = Integer.parseInt(System.getProperty("cubicchunks.debug.profiler.interval_ns", "1"));
25+
26+
@Unique private static final AsyncProfiler perf_PROFILER = AsyncProfiler.getInstance();
27+
@Unique private static boolean perf_started = false;
28+
@Unique private static int perf_idx = 0;
29+
30+
@Unique private static long perf_tickStartTime = 0;
31+
32+
static {
33+
try {
34+
FileUtils.deleteDirectory(perf_basePath.toFile());
35+
} catch (IOException e) {
36+
CubicChunks.LOGGER.error("[tick-profiler] Failed to clear existing output directory {}", perf_basePath, e);
37+
}
38+
}
39+
40+
@Inject(method = "tickServer", at = @At("HEAD"))
41+
private void onTick(BooleanSupplier hasTimeLeft, CallbackInfo ci) {
42+
if (!perf_doProfiling) {
43+
return;
44+
}
45+
46+
perf_stopProfiler();
47+
48+
// Start a new profiler
49+
Path path = perf_basePath.resolve(perf_idx++ + ".jfr").toAbsolutePath();
50+
try {
51+
Files.createDirectories(path.getParent());
52+
perf_PROFILER.execute("start,jfr,interval=" + perf_interval + ",event=cpu,file=" + path.toAbsolutePath());
53+
} catch (IOException e) {
54+
CubicChunks.LOGGER.error("[tick-profiler] Failed to start async-profiler", e);
55+
}
56+
perf_started = true;
57+
perf_tickStartTime = System.nanoTime();
58+
}
59+
60+
@Inject(method = "stopServer", at = @At("HEAD"))
61+
private void onStop(CallbackInfo ci) {
62+
perf_stopProfiler();
63+
}
64+
65+
@Unique private static void perf_stopProfiler() {
66+
if (perf_started) {
67+
// Stop the currently running profiler
68+
try {
69+
perf_PROFILER.execute("stop");
70+
} catch (IOException e) {
71+
CubicChunks.LOGGER.error("[tick-profiler] Failed to stop async-profiler", e);
72+
}
73+
perf_started = false;
74+
75+
// Rename the just stopped profiler output file to include its duration for easy sorting
76+
int previousIndex = perf_idx - 1;
77+
Duration duration = Duration.ofNanos(System.nanoTime() - perf_tickStartTime);
78+
try {
79+
Files.move(perf_basePath.resolve(previousIndex + ".jfr"), perf_basePath.resolve(duration.toMillis() + "_" + previousIndex + ".jfr"));
80+
} catch (IOException e) {
81+
CubicChunks.LOGGER.error("[tick-profiler] Failed to rename jfr file to include tick duration", e);
82+
}
83+
}
84+
}
85+
86+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
@ParametersAreNonnullByDefault
2+
@MethodsReturnNonnullByDefault
3+
package io.github.opencubicchunks.cubicchunks.mixin.debug.common;
4+
5+
import javax.annotation.ParametersAreNonnullByDefault;
6+
7+
import io.github.opencubicchunks.cc_core.annotation.MethodsReturnNonnullByDefault;

src/main/resources/META-INF/neoforge.mods.toml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,4 +76,7 @@ description='''${mod_description}'''
7676
config="${mod_id}.mixins.core.json"
7777

7878
[[mixins]]
79-
config="${mod_id}.mixins.access.json"
79+
config="${mod_id}.mixins.access.json"
80+
81+
[[mixins]]
82+
config="${mod_id}.mixins.debug.json"

0 commit comments

Comments
 (0)