Some profiling results

This commit is contained in:
Johannes Frohnmeyer 2022-01-24 15:04:03 +01:00
parent b14a8fbed1
commit 86e0f00253
Signed by: Johannes
GPG Key ID: E76429612C2929F4
10 changed files with 64 additions and 14 deletions

1
.gitignore vendored
View File

@ -5,3 +5,4 @@ run*/
imgui.ini imgui.ini
hs_err_pid* hs_err_pid*
inceptum.log inceptum.log
bin

View File

@ -47,7 +47,7 @@ public class InceptumGui {
try { try {
for (Path path : Utils.ls(MetaHolder.INSTANCE_DIR)) { for (Path path : Utils.ls(MetaHolder.INSTANCE_DIR)) {
if (Files.exists(path.resolve("instance.json"))) if (Files.exists(path.resolve("instance.json")))
ModsDirScanner.get(path, Utils.loadObject(path.resolve("instance.json"), InstanceMeta.class)).start(); ModsDirScanner.get(path.resolve("mods"), Utils.loadObject(path.resolve("instance.json"), InstanceMeta.class)).start();
} }
} catch (IOException e) { } catch (IOException e) {
Utils.LOGGER.error("Could not initialize MDS"); Utils.LOGGER.error("Could not initialize MDS");

View File

@ -13,6 +13,7 @@ import io.gitlab.jfronny.inceptum.model.mojang.VersionsList;
import io.gitlab.jfronny.inceptum.model.mojang.VersionsListInfo; import io.gitlab.jfronny.inceptum.model.mojang.VersionsListInfo;
import io.gitlab.jfronny.inceptum.util.ConfigHolder; import io.gitlab.jfronny.inceptum.util.ConfigHolder;
import io.gitlab.jfronny.inceptum.util.MetaHolder; import io.gitlab.jfronny.inceptum.util.MetaHolder;
import io.gitlab.jfronny.inceptum.util.Tuple;
import io.gitlab.jfronny.inceptum.util.Utils; import io.gitlab.jfronny.inceptum.util.Utils;
import io.gitlab.jfronny.inceptum.util.api.FabricMetaApi; import io.gitlab.jfronny.inceptum.util.api.FabricMetaApi;
import io.gitlab.jfronny.inceptum.util.api.McApi; import io.gitlab.jfronny.inceptum.util.api.McApi;
@ -33,6 +34,7 @@ public class InstanceManageControls {
private final ImInt fabricVersion = new ImInt(0); private final ImInt fabricVersion = new ImInt(0);
private final ImBoolean snapshots = new ImBoolean(ConfigHolder.CONFIG.snapshots); private final ImBoolean snapshots = new ImBoolean(ConfigHolder.CONFIG.snapshots);
private final ImBoolean fabric = new ImBoolean(true); private final ImBoolean fabric = new ImBoolean(true);
private final Map<Tuple<String, String>, VersionInfo> versionInfoCache = new HashMap<>();
private VersionsListInfo selected; private VersionsListInfo selected;
private FabricVersionLoaderInfo selectedFabric; private FabricVersionLoaderInfo selectedFabric;
@ -126,9 +128,13 @@ public class InstanceManageControls {
} }
public VersionInfo getVersionInfo() throws IOException { public VersionInfo getVersionInfo() throws IOException {
Tuple<String, String> key = new Tuple<>(selected.id, fabric.get() ? selectedFabric.loader.version : "");
if (!versionInfoCache.containsKey(key)) {
VersionInfo vi = McApi.getVersionInfo(selected); VersionInfo vi = McApi.getVersionInfo(selected);
if (fabric.get()) FabricMetaApi.addFabric(vi, selectedFabric.loader.version, FabricMetaApi.FabricVersionInfoType.Both); if (fabric.get()) FabricMetaApi.addFabric(vi, selectedFabric.loader.version, FabricMetaApi.FabricVersionInfoType.Both);
return vi; versionInfoCache.put(key, vi);
}
return versionInfoCache.get(key);
} }
public LoaderInfo getLoaderInfo() { public LoaderInfo getLoaderInfo() {

View File

@ -32,7 +32,7 @@ public class InstanceView {
} }
InstanceMeta instance; InstanceMeta instance;
try { try {
instance = Utils.loadObject(path.resolve("instance.json"), InstanceMeta.class); instance = Utils.loadObject(path.resolve("instance.json"), InstanceMeta.class); //TODO investigate the perf impact of this
} catch (IOException e) { } catch (IOException e) {
Utils.LOGGER.error("Could not load instance.json", e); Utils.LOGGER.error("Could not load instance.json", e);
continue; continue;

View File

@ -86,7 +86,7 @@ public class ModDescription {
public void addSource(ModSource source, String gameVersion) { public void addSource(ModSource source, String gameVersion) {
try { try {
sources.put(source, source.getUpdate(gameVersion)); sources.put(source, source.getUpdate(gameVersion)); //TODO only fetch updates on first check
} catch (IOException e) { } catch (IOException e) {
Utils.LOGGER.error("Could not check " + source.getName() + " for updates", e); Utils.LOGGER.error("Could not check " + source.getName() + " for updates", e);
} }

View File

@ -0,0 +1,4 @@
package io.gitlab.jfronny.inceptum.util;
public record Tuple<T1, T2>(T1 left, T2 right) {
}

View File

@ -72,7 +72,7 @@ public record FileScanTask(Path file, BiConsumer<Path, IWModDescription> discove
} }
ModSource selectedSource = null; ModSource selectedSource = null;
for (ModSource source : md.sources.keySet()) { for (ModSource source : md.sources.keySet()) {
source.getUpdate(gameVersion); source.getUpdate(gameVersion); //TODO only check once for ID
if (!Files.exists(source.getJarPath())) source.download(); if (!Files.exists(source.getJarPath())) source.download();
selectedSource = source; selectedSource = source;
} }

View File

@ -14,7 +14,7 @@ import java.util.function.BiConsumer;
public class ModsDirScanner implements Closeable { public class ModsDirScanner implements Closeable {
private static final Map<Path, ModsDirScanner> SCANNERS = new HashMap<>(); private static final Map<Path, ModsDirScanner> SCANNERS = new HashMap<>();
private static final ExecutorService POOL = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 2); private static final ExecutorService POOL = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors(), new NamedThreadFactory("mds"));
private final Map<Path, IWModDescription> descriptions = new HashMap<>(); private final Map<Path, IWModDescription> descriptions = new HashMap<>();
private final Set<Path> scannedPaths = new HashSet<>(); private final Set<Path> scannedPaths = new HashSet<>();
private final Thread th; private final Thread th;
@ -25,7 +25,7 @@ public class ModsDirScanner implements Closeable {
private ModsDirScanner(Path modsDir, InstanceMeta instance) { private ModsDirScanner(Path modsDir, InstanceMeta instance) {
this.modsDir = modsDir; this.modsDir = modsDir;
this.instance = instance; this.instance = instance;
this.th = new Thread(this::scanTaskInternal); this.th = new Thread(this::scanTaskInternal, "mds-" + modsDir.getParent().getFileName());
} }
public static ModsDirScanner get(Path modsDir, InstanceMeta instance) { public static ModsDirScanner get(Path modsDir, InstanceMeta instance) {
@ -92,20 +92,29 @@ public class ModsDirScanner implements Closeable {
private void scanTaskInternal() { private void scanTaskInternal() {
while (!disposed) { while (!disposed) {
runOnce(descriptions::put); runOnce((path, iwModDescription) -> {});
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
} }
} }
public void runOnce(BiConsumer<Path, IWModDescription> discovered) { public void runOnce(BiConsumer<Path, IWModDescription> discovered) {
try { try {
if (!Files.isDirectory(modsDir)) { if (!Files.isDirectory(modsDir)) {
Thread.sleep(5000);
return; return;
} }
Set<Future<?>> tasks = new HashSet<>(); Set<Future<?>> tasks = new HashSet<>();
String mc = instance.getMinecraftVersion();
discovered = discovered.andThen((path, iwModDescription) -> {
scannedPaths.add(path);
descriptions.put(path, iwModDescription);
});
for (Path mods : Utils.ls(modsDir)) { for (Path mods : Utils.ls(modsDir)) {
if (disposed) return; if (disposed) return;
tasks.add(POOL.submit(new FileScanTask(mods, discovered.andThen((path, iwModDescription) -> scannedPaths.add(path)), getGameVersion()))); tasks.add(POOL.submit(new FileScanTask(mods, discovered, mc)));
} }
for (Future<?> task : tasks) { for (Future<?> task : tasks) {
try { try {
@ -114,7 +123,6 @@ public class ModsDirScanner implements Closeable {
Utils.LOGGER.error("Failed to execute ScanTask", e); Utils.LOGGER.error("Failed to execute ScanTask", e);
} }
} }
Thread.sleep(100);
} catch (IOException | InterruptedException e) { } catch (IOException | InterruptedException e) {
Utils.LOGGER.error("Could not list mods", e); Utils.LOGGER.error("Could not list mods", e);
} }

View File

@ -0,0 +1,30 @@
package io.gitlab.jfronny.inceptum.util.mds;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;
public class NamedThreadFactory implements ThreadFactory {
private static final AtomicInteger poolNumber = new AtomicInteger(1);
private final ThreadGroup group;
private final AtomicInteger threadNumber = new AtomicInteger(1);
private final String namePrefix;
public NamedThreadFactory(String name) {
SecurityManager s = System.getSecurityManager();
this.group = s != null ? s.getThreadGroup() : Thread.currentThread().getThreadGroup();
this.namePrefix = name + "-pool-" + poolNumber.getAndIncrement() + "-thread-";
}
public Thread newThread(Runnable r) {
Thread t = new Thread(this.group, r, this.namePrefix + this.threadNumber.getAndIncrement(), 0L);
if (t.isDaemon()) {
t.setDaemon(false);
}
if (t.getPriority() != 5) {
t.setPriority(5);
}
return t;
}
}

View File

@ -56,6 +56,7 @@ public class Utils {
return downloadObject(url, () -> downloadString(url, sha1), s -> GsonHolder.getGson().fromJson(s, type)); return downloadObject(url, () -> downloadString(url, sha1), s -> GsonHolder.getGson().fromJson(s, type));
} }
//TODO memory-based cache to avoid gson
private static <T> T downloadObject(String url, ThrowingSupplier<String, Exception> sourceString, Function<String, T> builder) throws IOException { private static <T> T downloadObject(String url, ThrowingSupplier<String, Exception> sourceString, Function<String, T> builder) throws IOException {
Path cache = MetaHolder.CACHE_DIR.resolve(HashUtils.sha1(url.getBytes(StandardCharsets.UTF_8))); Path cache = MetaHolder.CACHE_DIR.resolve(HashUtils.sha1(url.getBytes(StandardCharsets.UTF_8)));
if (Files.exists(cache)) if (Files.exists(cache))