Scan for all Block classes and preload them on worker threads
This helps move towards multithreading most VoxelShape computations
This commit is contained in:
parent
9ebeec6fc2
commit
c6323fd62e
|
|
@ -29,6 +29,7 @@ public class ModernFixEarlyConfig {
|
|||
this.addMixinRule("bugfix.edge_chunk_not_saved", true);
|
||||
this.addMixinRule("perf.async_jei", true);
|
||||
this.addMixinRule("perf.thread_priorities", true);
|
||||
this.addMixinRule("perf.preload_block_classes", true);
|
||||
|
||||
/* Mod compat */
|
||||
if(FMLLoader.getLoadingModList().getModFileById("smoothboot") != null) {
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ public abstract class ModelBakeryMixin {
|
|||
.filter(pair -> pair.getValue() != null)
|
||||
.collect(Collectors.toConcurrentMap(Pair::getKey, Pair::getValue));
|
||||
useModelCache = true;
|
||||
ModernFix.LOGGER.warn("Preloading JSONs took " + stopwatch.elapsed(TimeUnit.SECONDS) + " seconds");
|
||||
ModernFix.LOGGER.warn("Preloading JSONs took " + stopwatch.elapsed(TimeUnit.MILLISECONDS)/1000f + " seconds");
|
||||
stopwatch.stop();
|
||||
}
|
||||
|
||||
|
|
@ -121,7 +121,7 @@ public abstract class ModelBakeryMixin {
|
|||
}).forEach((textureReferenceErrors) -> {
|
||||
ModernFix.LOGGER.warn("Unable to resolve texture reference: {} in {}", textureReferenceErrors.getFirst(), textureReferenceErrors.getSecond());
|
||||
});
|
||||
ModernFix.LOGGER.warn("Collecting textures took " + stopwatch.elapsed(TimeUnit.SECONDS) + " seconds");
|
||||
ModernFix.LOGGER.warn("Collecting textures took " + stopwatch.elapsed(TimeUnit.MILLISECONDS)/1000f + " seconds");
|
||||
stopwatch.stop();
|
||||
return materials;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,20 @@
|
|||
package org.embeddedt.modernfix.mixin.perf.preload_block_classes;
|
||||
|
||||
import net.minecraftforge.fml.ModLoadingStage;
|
||||
import net.minecraftforge.registries.GameData;
|
||||
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;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.embeddedt.modernfix.util.BlockClassPreloader;
|
||||
|
||||
@Mixin(GameData.class)
|
||||
public class GameDataMixin {
|
||||
@Inject(method = "generateRegistryEvents", at = @At("RETURN"), remap = false)
|
||||
private static void preloadBlockClasses(CallbackInfoReturnable<Stream<ModLoadingStage.EventGenerator<?>>> cir) {
|
||||
BlockClassPreloader.preloadClasses();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
package org.embeddedt.modernfix.util;
|
||||
|
||||
import com.google.common.base.Stopwatch;
|
||||
import net.minecraft.block.AbstractBlock;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraftforge.fml.ModList;
|
||||
import net.minecraftforge.fml.ModWorkManager;
|
||||
import net.minecraftforge.fml.loading.moddiscovery.ModFile;
|
||||
import net.minecraftforge.fml.loading.moddiscovery.ModFileInfo;
|
||||
import net.minecraftforge.forgespi.language.ModFileScanData;
|
||||
import org.embeddedt.modernfix.ModernFix;
|
||||
import org.objectweb.asm.Type;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class BlockClassPreloader {
|
||||
public static void preloadClasses() {
|
||||
Stopwatch stopwatch = Stopwatch.createStarted();
|
||||
ModernFix.LOGGER.warn("Preparing to preload classes...");
|
||||
HashMap<Type, Boolean> isABlockClass = new HashMap<>();
|
||||
isABlockClass.put(Type.getType(AbstractBlock.class), true);
|
||||
isABlockClass.put(Type.getType(Block.class), true);
|
||||
Field selfField, parentField;
|
||||
List<CompletableFuture> futures = new ArrayList<>();
|
||||
try {
|
||||
selfField = ModFileScanData.ClassData.class.getDeclaredField("clazz");
|
||||
selfField.setAccessible(true);
|
||||
parentField = ModFileScanData.ClassData.class.getDeclaredField("parent");
|
||||
parentField.setAccessible(true);
|
||||
List<ModFileScanData.ClassData> currentCandidates = ModList.get().getModFiles().stream()
|
||||
.map(ModFileInfo::getFile)
|
||||
.map(ModFile::getScanResult)
|
||||
.flatMap(data -> data.getClasses().stream())
|
||||
.collect(Collectors.toList());
|
||||
HashSet<Type> blockClasses = new HashSet<>();
|
||||
blockClasses.add(Type.getType(AbstractBlock.class));
|
||||
HashSet<Type> nonBlockClasses = new HashSet<>();
|
||||
int previousSize = -1;
|
||||
nonBlockClasses.add(Type.getType(Object.class));
|
||||
currentCandidates.removeIf(clz -> {
|
||||
Type self;
|
||||
try {
|
||||
self = (Type)selfField.get(clz);
|
||||
} catch(ReflectiveOperationException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return (nonBlockClasses.contains(self) || blockClasses.contains(self));
|
||||
});
|
||||
while(blockClasses.size() > previousSize && currentCandidates.size() > 0) {
|
||||
previousSize = blockClasses.size();
|
||||
currentCandidates.removeIf(clz -> {
|
||||
Type parent, self;
|
||||
try {
|
||||
parent = (Type)parentField.get(clz);
|
||||
self = (Type)selfField.get(clz);
|
||||
} catch(ReflectiveOperationException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
if(nonBlockClasses.contains(parent)) {
|
||||
nonBlockClasses.add(self);
|
||||
return true;
|
||||
} else if(blockClasses.contains(parent)) {
|
||||
blockClasses.add(self);
|
||||
futures.add(CompletableFuture.runAsync(() -> {
|
||||
if(self.getClassName().toLowerCase(Locale.ROOT).contains("mixin"))
|
||||
return;
|
||||
try {
|
||||
Class.forName(self.getClassName());
|
||||
} catch(Throwable e) {
|
||||
ModernFix.LOGGER.warn("Couldn't load " + self.getClassName(), e);
|
||||
}
|
||||
}, ModWorkManager.parallelExecutor()));
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
});
|
||||
}
|
||||
futures.forEach(CompletableFuture::join);
|
||||
} catch(ReflectiveOperationException e) {
|
||||
throw new RuntimeException(e);
|
||||
} finally {
|
||||
ModernFix.LOGGER.warn("Preloading classes took " + stopwatch.elapsed(TimeUnit.MILLISECONDS)/1000f + " seconds");
|
||||
stopwatch.stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -17,7 +17,8 @@
|
|||
"perf.reduce_blockstate_cache_rebuilds.GameDataMixin",
|
||||
"perf.reduce_blockstate_cache_rebuilds.BlockCallbacksMixin",
|
||||
"perf.boost_worker_count.UtilMixin",
|
||||
"perf.thread_priorities.UtilMixin"
|
||||
"perf.thread_priorities.UtilMixin",
|
||||
"perf.preload_block_classes.GameDataMixin"
|
||||
],
|
||||
"client": [
|
||||
"perf.skip_first_datapack_reload.MinecraftMixin",
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user