caching/performance improvements
This commit is contained in:
		
							parent
							
								
									ac9c7fc103
								
							
						
					
					
						commit
						3c7d6fd87f
					
				
					 6 changed files with 165 additions and 18 deletions
				
			
		|  | @ -12,7 +12,7 @@ targetCompatibility = 1.8 | |||
| 
 | ||||
| group = 'net.fabricmc' | ||||
| archivesBaseName = project.name | ||||
| version = '0.2.290-SNAPSHOT' | ||||
| version = '0.2.5-SNAPSHOT' | ||||
| 
 | ||||
| def build = "local" | ||||
| def ENV = System.getenv() | ||||
|  |  | |||
							
								
								
									
										65
									
								
								src/main/java/net/fabricmc/loom/providers/MappingsCache.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								src/main/java/net/fabricmc/loom/providers/MappingsCache.java
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,65 @@ | |||
| /* | ||||
|  * This file is part of fabric-loom, licensed under the MIT License (MIT). | ||||
|  * | ||||
|  * Copyright (c) 2016, 2017, 2018 FabricMC | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|  * of this software and associated documentation files (the "Software"), to deal | ||||
|  * in the Software without restriction, including without limitation the rights | ||||
|  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
|  * copies of the Software, and to permit persons to whom the Software is | ||||
|  * furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be included in all | ||||
|  * copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
|  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
|  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
|  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
|  * SOFTWARE. | ||||
|  */ | ||||
| 
 | ||||
| package net.fabricmc.loom.providers; | ||||
| 
 | ||||
| import net.fabricmc.loom.util.StaticPathWatcher; | ||||
| import net.fabricmc.mappings.Mappings; | ||||
| import org.gradle.api.logging.Logging; | ||||
| 
 | ||||
| import java.io.FileInputStream; | ||||
| import java.io.IOException; | ||||
| import java.io.InputStream; | ||||
| import java.lang.ref.SoftReference; | ||||
| import java.nio.file.*; | ||||
| import java.util.HashMap; | ||||
| import java.util.Map; | ||||
| 
 | ||||
| public final class MappingsCache { | ||||
|     public static final MappingsCache INSTANCE = new MappingsCache(); | ||||
| 
 | ||||
|     private final Map<Path, SoftReference<Mappings>> mappingsCache = new HashMap<>(); | ||||
| 
 | ||||
|     public Mappings get(Path mappingsPath) { | ||||
|         mappingsPath = mappingsPath.toAbsolutePath(); | ||||
|         if (StaticPathWatcher.INSTANCE.hasFileChanged(mappingsPath)) { | ||||
|             mappingsCache.remove(mappingsPath); | ||||
|         } | ||||
| 
 | ||||
|         SoftReference<Mappings> ref = mappingsCache.get(mappingsPath); | ||||
|         if (ref != null && ref.get() != null) { | ||||
|             return ref.get(); | ||||
|         } else { | ||||
|             try (InputStream stream = Files.newInputStream(mappingsPath)) { | ||||
|                 Logging.getLogger(MappingsCache.class).lifecycle("CACHE MISS! OWO " + mappingsPath); | ||||
|                 Mappings mappings = net.fabricmc.mappings.MappingsProvider.readTinyMappings(stream, false); | ||||
|                 ref = new SoftReference<>(mappings); | ||||
|                 mappingsCache.put(mappingsPath, ref); | ||||
|                 return mappings; | ||||
|             } catch (IOException e) { | ||||
|                 throw new RuntimeException(e); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -56,18 +56,8 @@ public class MappingsProvider extends DependencyProvider { | |||
| 	public File MAPPINGS_TINY; | ||||
| 	public File MAPPINGS_MIXIN_EXPORT; | ||||
| 
 | ||||
| 	private SoftReference<Mappings> mappings; | ||||
| 
 | ||||
| 	public Mappings getMappings() throws IOException { | ||||
| 		if (mappings == null || mappings.get() == null) { | ||||
| 			try (FileInputStream stream = new FileInputStream(MAPPINGS_TINY)) { | ||||
| 				mappings = new SoftReference<>( | ||||
| 						net.fabricmc.mappings.MappingsProvider.readTinyMappings(stream, false) | ||||
| 				); | ||||
| 			} | ||||
| 		} | ||||
| 		 | ||||
| 		return mappings.get(); | ||||
| 		return MappingsCache.INSTANCE.get(MAPPINGS_TINY.toPath()); | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
|  |  | |||
|  | @ -124,8 +124,10 @@ public class MinecraftProvider extends DependencyProvider { | |||
| 				throw new GradleException("Version manifests not found at " + manifests.getAbsolutePath()); | ||||
| 			} | ||||
| 		} else { | ||||
| 			project.getLogger().debug("Downloading version manifests"); | ||||
| 			DownloadUtil.downloadIfChanged(new URL("https://launchermeta.mojang.com/mc/game/version_manifest.json"), manifests, project.getLogger()); | ||||
| 			if (StaticPathWatcher.INSTANCE.hasFileChanged(manifests.toPath())) { | ||||
| 				project.getLogger().debug("Downloading version manifests"); | ||||
| 				DownloadUtil.downloadIfChanged(new URL("https://launchermeta.mojang.com/mc/game/version_manifest.json"), manifests, project.getLogger()); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		String versionManifest = Files.asCharSource(manifests, StandardCharsets.UTF_8).read(); | ||||
|  | @ -142,8 +144,10 @@ public class MinecraftProvider extends DependencyProvider { | |||
| 					throw new GradleException("Minecraft " + minecraftVersion + " manifest not found at " + MINECRAFT_JSON.getAbsolutePath()); | ||||
| 				} | ||||
| 			} else { | ||||
| 				project.getLogger().debug("Downloading Minecraft {} manifest", minecraftVersion); | ||||
| 				DownloadUtil.downloadIfChanged(new URL(optionalVersion.get().url), MINECRAFT_JSON, project.getLogger()); | ||||
| 				if (StaticPathWatcher.INSTANCE.hasFileChanged(MINECRAFT_JSON.toPath())) { | ||||
| 					project.getLogger().debug("Downloading Minecraft {} manifest", minecraftVersion); | ||||
| 					DownloadUtil.downloadIfChanged(new URL(optionalVersion.get().url), MINECRAFT_JSON, project.getLogger()); | ||||
| 				} | ||||
| 			} | ||||
| 		} else { | ||||
| 			throw new RuntimeException("Failed to find minecraft version: " + minecraftVersion); | ||||
|  | @ -152,12 +156,12 @@ public class MinecraftProvider extends DependencyProvider { | |||
| 	} | ||||
| 
 | ||||
| 	private void downloadJars(Logger logger) throws IOException { | ||||
| 		if (!MINECRAFT_CLIENT_JAR.exists() || !Checksum.equals(MINECRAFT_CLIENT_JAR, versionInfo.downloads.get("client").sha1)) { | ||||
| 		if (!MINECRAFT_CLIENT_JAR.exists() || (!Checksum.equals(MINECRAFT_CLIENT_JAR, versionInfo.downloads.get("client").sha1) && StaticPathWatcher.INSTANCE.hasFileChanged(MINECRAFT_CLIENT_JAR.toPath()))) { | ||||
| 			logger.debug("Downloading Minecraft {} client jar", minecraftVersion); | ||||
| 			DownloadUtil.downloadIfChanged(new URL(versionInfo.downloads.get("client").url), MINECRAFT_CLIENT_JAR, logger); | ||||
| 		} | ||||
| 
 | ||||
| 		if (!MINECRAFT_SERVER_JAR.exists() || !Checksum.equals(MINECRAFT_SERVER_JAR, versionInfo.downloads.get("server").sha1)) { | ||||
| 		if (!MINECRAFT_SERVER_JAR.exists() || (!Checksum.equals(MINECRAFT_SERVER_JAR, versionInfo.downloads.get("server").sha1) && StaticPathWatcher.INSTANCE.hasFileChanged(MINECRAFT_SERVER_JAR.toPath()))) { | ||||
| 			logger.debug("Downloading Minecraft {} server jar", minecraftVersion); | ||||
| 			DownloadUtil.downloadIfChanged(new URL(versionInfo.downloads.get("server").url), MINECRAFT_SERVER_JAR, logger); | ||||
| 		} | ||||
|  |  | |||
|  | @ -27,11 +27,15 @@ package net.fabricmc.loom.util; | |||
| import com.google.common.hash.HashCode; | ||||
| import com.google.common.hash.Hashing; | ||||
| import com.google.common.io.Files; | ||||
| import org.gradle.api.logging.Logger; | ||||
| import org.gradle.api.logging.Logging; | ||||
| 
 | ||||
| import java.io.File; | ||||
| import java.io.IOException; | ||||
| 
 | ||||
| public class Checksum { | ||||
| 	private static final Logger log = Logging.getLogger(Checksum.class); | ||||
| 
 | ||||
| 	public static boolean equals(File file, String checksum) { | ||||
| 		if (file == null) { | ||||
| 			return false; | ||||
|  | @ -43,6 +47,7 @@ public class Checksum { | |||
| 			for (Byte hashBytes : hash.asBytes()) { | ||||
| 				builder.append(Integer.toString((hashBytes & 0xFF) + 0x100, 16).substring(1)); | ||||
| 			} | ||||
| 			log.debug("Checksum check: '" + builder.toString() + "' == '" + checksum + "'?"); | ||||
| 			return builder.toString().equals(checksum); | ||||
| 		} catch (IOException e) { | ||||
| 			e.printStackTrace(); | ||||
|  |  | |||
							
								
								
									
										83
									
								
								src/main/java/net/fabricmc/loom/util/StaticPathWatcher.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								src/main/java/net/fabricmc/loom/util/StaticPathWatcher.java
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,83 @@ | |||
| /* | ||||
|  * This file is part of fabric-loom, licensed under the MIT License (MIT). | ||||
|  * | ||||
|  * Copyright (c) 2016, 2017, 2018 FabricMC | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|  * of this software and associated documentation files (the "Software"), to deal | ||||
|  * in the Software without restriction, including without limitation the rights | ||||
|  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
|  * copies of the Software, and to permit persons to whom the Software is | ||||
|  * furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be included in all | ||||
|  * copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
|  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
|  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
|  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
|  * SOFTWARE. | ||||
|  */ | ||||
| 
 | ||||
| package net.fabricmc.loom.util; | ||||
| 
 | ||||
| import net.fabricmc.mappings.Mappings; | ||||
| import org.gradle.api.logging.Logging; | ||||
| 
 | ||||
| import java.io.IOException; | ||||
| import java.io.InputStream; | ||||
| import java.lang.ref.SoftReference; | ||||
| import java.nio.file.*; | ||||
| import java.util.HashMap; | ||||
| import java.util.Map; | ||||
| 
 | ||||
| public final class StaticPathWatcher { | ||||
|     public static final StaticPathWatcher INSTANCE = new StaticPathWatcher(); | ||||
| 
 | ||||
|     private final Map<Path, Boolean> changeCache = new HashMap<>(); | ||||
|     private final WatchService service; | ||||
|     private final Map<Path, WatchKey> pathsObserved = new HashMap<>(); | ||||
| 
 | ||||
|     private StaticPathWatcher() { | ||||
|         try { | ||||
|             service = FileSystems.getDefault().newWatchService(); | ||||
|         } catch (IOException e) { | ||||
|             throw new RuntimeException(e); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     public boolean hasFileChanged(Path filePath) { | ||||
|         WatchKey key; | ||||
|         while ((key = service.poll()) != null) { | ||||
|             for (WatchEvent<?> event : key.pollEvents()) { | ||||
|                 Object ctx = event.context(); | ||||
|                 if (ctx instanceof Path) { | ||||
|                     changeCache.put(((Path) ctx).toAbsolutePath(), true); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         filePath = filePath.toAbsolutePath(); | ||||
|         Path parentPath = filePath.getParent(); | ||||
|         if (changeCache.containsKey(filePath)) { | ||||
|             return true; | ||||
|         } else { | ||||
|             if (!pathsObserved.containsKey(parentPath)) { | ||||
|                 try { | ||||
|                     pathsObserved.put(parentPath, parentPath.register( | ||||
|                             service, StandardWatchEventKinds.ENTRY_MODIFY, StandardWatchEventKinds.ENTRY_DELETE | ||||
|                     )); | ||||
| 
 | ||||
|                     return true; | ||||
|                 } catch (IOException e) { | ||||
|                     throw new RuntimeException(e); | ||||
|                 } | ||||
|             } else { | ||||
|                 return false; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
		Loading…
	
		Reference in a new issue