Skip to content

Repository files navigation

WhySoSlow

A Minecraft mod that performs extremely detailed performance analysis of mods during startup, world loading, and world generation.

Supported Versions

WhySoSlow is released for multiple Minecraft versions on separate branches:

Branch Minecraft Loader Java
1.20.1 1.20.1 Forge 17
1.21.1 1.21.1 NeoForge 21
26.1 26.1 NeoForge 25

Artifacts are published to maven.breakinblocks.com with version format <minecraft-version>-<mod-version> (e.g., whysoslow-1.21.1-1.0.4.jar) and attached to GitHub releases tagged v<minecraft-version>-<mod-version>.

WARNING

This mod is a debugging tool only. Do not ship it in production modpacks.

WhySoSlow uses Mixin to inject into loader internals and Minecraft's worldgen pipeline. Where loader internals cannot be transformed (module-layer classes), it uses reflection to wrap event bus listeners directly. This means:

  • It is itself a source of performance loss. Every mod event, every placed feature, every structure, every carver, and every noise fill operation is wrapped with timing instrumentation. This overhead is unavoidable and will make your game slower while the mod is installed.
  • It mixes into critical code paths. Mixin class transformations are applied to Minecraft worldgen classes including MinecraftServer, ChunkGenerator, NoiseBasedChunkGenerator, PlacedFeature, StructureStart, and ConfiguredWorldCarver. While these injections are carefully written, they carry inherent risk.
  • It modifies event bus listener lists at runtime. To capture per-mod timing during startup and world load, WhySoSlow uses reflection to wrap every other mod's registered event handlers.
  • Install it, collect your data, then remove it. Do not leave this mod installed longer than necessary.

What It Does

Startup Profiling (Automatic)

On every game launch, WhySoSlow times every mod's handling of every lifecycle event. When loading completes, a report is written to:

logs/whysoslow/startup.log

The report includes for every mod, sorted slowest to fastest:

  • Wall-clock time, CPU time, and memory delta per loading phase (Construction, Registry, Common Setup, Client Setup, Load Complete)
  • Registry entry counts (blocks, items, entities, etc.)
  • Overall phase breakdown and total startup time

World Load Profiling (Automatic)

When you load into a world, WhySoSlow measures dimension creation time, memory usage, and per-mod contributions during the server start lifecycle. A report is written to:

logs/whysoslow/worldload.log

World Generation Profiling (On-Demand)

Use the /whysoslow command to profile runtime world generation:

Command Description
/whysoslow start Begin profiling. Builds registry lookup maps and starts recording all worldgen operations.
/whysoslow stop Stop profiling and write the report.
/whysoslow status Show current profiling state and stats.

Explore the world while profiling is active to generate chunks, then stop to get your report at:

logs/whysoslow/worldgen.log

The worldgen report breaks down:

  • Overall category split - Noise generation, surface building, feature placement, structure generation, and carvers with percentages
  • Every placed feature - Total time, average time, max time, and call count, attributed to the owning mod
  • Features grouped by mod - Which mods' worldgen features cost the most
  • Every structure - Generation time per structure type
  • Every carver - Cave/ravine carving time per carver type

Mixin Targets

Mixin Target Purpose
MixinMinecraftServer MinecraftServer.createLevels / prepareLevels Dimension creation and chunk load timing
MixinServerLevel ServerLevel.<init> Per-dimension construction timing
MixinChunkGenerator ChunkGenerator.applyBiomeDecoration Per-chunk decoration timing
MixinNoiseBasedChunkGenerator fillFromNoise, buildSurface Terrain and surface timing
MixinPlacedFeature PlacedFeature.placeWithBiomeCheck Per-feature timing
MixinStructureStart StructureStart.placeInChunk Per-structure timing
MixinConfiguredWorldCarver ConfiguredWorldCarver.carve Per-carver timing

Building

Each branch targets a specific Java version (see the table above). Point JAVA_HOME at the matching JDK before running Gradle:

export JAVA_HOME="/path/to/matching-jdk"
./gradlew build

Output JAR will be in build/libs/.

License

MIT License

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages