From 17fb2b4656f8f78bc578b35f8285edb03789f4d1 Mon Sep 17 00:00:00 2001 From: shedaniel Date: Fri, 29 Jan 2021 23:38:46 +0800 Subject: [PATCH] Cache the checksum of asset index files. (#335) * Cache the checksum of asset index files. * Resolve reviews --- .../assets/MinecraftAssetsProvider.java | 51 +++++++++++++++++-- 1 file changed, 48 insertions(+), 3 deletions(-) diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/assets/MinecraftAssetsProvider.java b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/assets/MinecraftAssetsProvider.java index 7b1ff14..b191343 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/assets/MinecraftAssetsProvider.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/assets/MinecraftAssetsProvider.java @@ -26,20 +26,27 @@ package net.fabricmc.loom.configuration.providers.minecraft.assets; import java.io.File; import java.io.FileReader; +import java.io.FileWriter; import java.io.IOException; import java.net.URL; import java.util.Deque; +import java.util.HashMap; import java.util.Map; import java.util.concurrent.ConcurrentLinkedDeque; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; +import com.google.common.base.Stopwatch; +import com.google.common.hash.Hashing; +import com.google.common.io.Files; import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; import org.gradle.api.GradleException; import org.gradle.api.Project; import net.fabricmc.loom.LoomGradleExtension; +import net.fabricmc.loom.LoomGradlePlugin; import net.fabricmc.loom.configuration.providers.MinecraftProvider; import net.fabricmc.loom.configuration.providers.minecraft.MinecraftVersionInfo; import net.fabricmc.loom.util.Checksum; @@ -63,6 +70,7 @@ public class MinecraftAssetsProvider { } File assetsInfo = new File(assets, "indexes" + File.separator + assetIndex.getFabricId(minecraftProvider.getMinecraftVersion()) + ".json"); + File checksumInfo = new File(assets, "checksum" + File.separator + minecraftProvider.getMinecraftVersion() + ".json"); if (!assetsInfo.exists() || !Checksum.equals(assetsInfo, assetIndex.sha1)) { project.getLogger().lifecycle(":downloading asset index"); @@ -80,17 +88,28 @@ public class MinecraftAssetsProvider { } } - project.getLogger().lifecycle(":downloading assets..."); + Gson gson = new Gson(); + Map checksumInfos = new HashMap<>(); + + if (checksumInfo.exists()) { + try (FileReader reader = new FileReader(checksumInfo)) { + checksumInfos.putAll(gson.fromJson(reader, new TypeToken>() { + }.getType())); + } + } Deque loggers = new ConcurrentLinkedDeque<>(); ExecutorService executor = Executors.newFixedThreadPool(Math.min(10, Math.max(Runtime.getRuntime().availableProcessors() / 2, 1))); + int toDownload = 0; AssetIndex index; try (FileReader fileReader = new FileReader(assetsInfo)) { - index = new Gson().fromJson(fileReader, AssetIndex.class); + index = gson.fromJson(fileReader, AssetIndex.class); } + Stopwatch stopwatch = Stopwatch.createStarted(); + Map parent = index.getFileMap(); for (Map.Entry entry : parent.entrySet()) { @@ -99,7 +118,16 @@ public class MinecraftAssetsProvider { String filename = "objects" + File.separator + sha1.substring(0, 2) + File.separator + sha1; File file = new File(assets, filename); - if (!file.exists() || !Checksum.equals(file, sha1)) { + String localFileChecksum = !file.exists() ? null : checksumInfos.computeIfAbsent(entry.getKey(), path -> { + try { + return Files.asByteSource(file).hash(Hashing.sha1()).toString(); + } catch (IOException e) { + e.printStackTrace(); + return null; + } + }); + + if (LoomGradlePlugin.refreshDeps || localFileChecksum == null || !localFileChecksum.equals(sha1)) { if (offline) { if (file.exists()) { project.getLogger().warn("Outdated asset " + entry.getKey()); @@ -107,6 +135,7 @@ public class MinecraftAssetsProvider { throw new GradleException("Asset " + entry.getKey() + " not found at " + file.getAbsolutePath()); } } else { + toDownload++; executor.execute(() -> { ProgressLogger progressLogger; @@ -135,6 +164,10 @@ public class MinecraftAssetsProvider { throw new RuntimeException("Failed to download: " + assetName, e); } + if (localFileChecksum == null) { + checksumInfos.put(entry.getKey(), sha1); + } + //Give this logger back loggers.add(progressLogger); }); @@ -142,6 +175,18 @@ public class MinecraftAssetsProvider { } } + project.getLogger().info("Took " + stopwatch.stop() + " to iterate " + parent.size() + " asset index."); + + if (toDownload > 0) { + project.getLogger().lifecycle(":downloading " + toDownload + " asset" + (toDownload == 1 ? "" : "s") + "..."); + } + + checksumInfo.getParentFile().mkdirs(); + + try (FileWriter writer = new FileWriter(checksumInfo)) { + gson.toJson(checksumInfos, writer); + } + //Wait for the assets to all download executor.shutdown();