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' | group = 'net.fabricmc' | ||||||
| archivesBaseName = project.name | archivesBaseName = project.name | ||||||
| version = '0.2.290-SNAPSHOT' | version = '0.2.5-SNAPSHOT' | ||||||
| 
 | 
 | ||||||
| def build = "local" | def build = "local" | ||||||
| def ENV = System.getenv() | 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_TINY; | ||||||
| 	public File MAPPINGS_MIXIN_EXPORT; | 	public File MAPPINGS_MIXIN_EXPORT; | ||||||
| 
 | 
 | ||||||
| 	private SoftReference<Mappings> mappings; |  | ||||||
| 
 |  | ||||||
| 	public Mappings getMappings() throws IOException { | 	public Mappings getMappings() throws IOException { | ||||||
| 		if (mappings == null || mappings.get() == null) { | 		return MappingsCache.INSTANCE.get(MAPPINGS_TINY.toPath()); | ||||||
| 			try (FileInputStream stream = new FileInputStream(MAPPINGS_TINY)) { |  | ||||||
| 				mappings = new SoftReference<>( |  | ||||||
| 						net.fabricmc.mappings.MappingsProvider.readTinyMappings(stream, false) |  | ||||||
| 				); |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 		 |  | ||||||
| 		return mappings.get(); |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	@Override | 	@Override | ||||||
|  |  | ||||||
|  | @ -124,8 +124,10 @@ public class MinecraftProvider extends DependencyProvider { | ||||||
| 				throw new GradleException("Version manifests not found at " + manifests.getAbsolutePath()); | 				throw new GradleException("Version manifests not found at " + manifests.getAbsolutePath()); | ||||||
| 			} | 			} | ||||||
| 		} else { | 		} else { | ||||||
| 			project.getLogger().debug("Downloading version manifests"); | 			if (StaticPathWatcher.INSTANCE.hasFileChanged(manifests.toPath())) { | ||||||
| 			DownloadUtil.downloadIfChanged(new URL("https://launchermeta.mojang.com/mc/game/version_manifest.json"), manifests, project.getLogger()); | 				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(); | 		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()); | 					throw new GradleException("Minecraft " + minecraftVersion + " manifest not found at " + MINECRAFT_JSON.getAbsolutePath()); | ||||||
| 				} | 				} | ||||||
| 			} else { | 			} else { | ||||||
| 				project.getLogger().debug("Downloading Minecraft {} manifest", minecraftVersion); | 				if (StaticPathWatcher.INSTANCE.hasFileChanged(MINECRAFT_JSON.toPath())) { | ||||||
| 				DownloadUtil.downloadIfChanged(new URL(optionalVersion.get().url), MINECRAFT_JSON, project.getLogger()); | 					project.getLogger().debug("Downloading Minecraft {} manifest", minecraftVersion); | ||||||
|  | 					DownloadUtil.downloadIfChanged(new URL(optionalVersion.get().url), MINECRAFT_JSON, project.getLogger()); | ||||||
|  | 				} | ||||||
| 			} | 			} | ||||||
| 		} else { | 		} else { | ||||||
| 			throw new RuntimeException("Failed to find minecraft version: " + minecraftVersion); | 			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 { | 	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); | 			logger.debug("Downloading Minecraft {} client jar", minecraftVersion); | ||||||
| 			DownloadUtil.downloadIfChanged(new URL(versionInfo.downloads.get("client").url), MINECRAFT_CLIENT_JAR, logger); | 			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); | 			logger.debug("Downloading Minecraft {} server jar", minecraftVersion); | ||||||
| 			DownloadUtil.downloadIfChanged(new URL(versionInfo.downloads.get("server").url), MINECRAFT_SERVER_JAR, logger); | 			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.HashCode; | ||||||
| import com.google.common.hash.Hashing; | import com.google.common.hash.Hashing; | ||||||
| import com.google.common.io.Files; | 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.File; | ||||||
| import java.io.IOException; | import java.io.IOException; | ||||||
| 
 | 
 | ||||||
| public class Checksum { | public class Checksum { | ||||||
|  | 	private static final Logger log = Logging.getLogger(Checksum.class); | ||||||
|  | 
 | ||||||
| 	public static boolean equals(File file, String checksum) { | 	public static boolean equals(File file, String checksum) { | ||||||
| 		if (file == null) { | 		if (file == null) { | ||||||
| 			return false; | 			return false; | ||||||
|  | @ -43,6 +47,7 @@ public class Checksum { | ||||||
| 			for (Byte hashBytes : hash.asBytes()) { | 			for (Byte hashBytes : hash.asBytes()) { | ||||||
| 				builder.append(Integer.toString((hashBytes & 0xFF) + 0x100, 16).substring(1)); | 				builder.append(Integer.toString((hashBytes & 0xFF) + 0x100, 16).substring(1)); | ||||||
| 			} | 			} | ||||||
|  | 			log.debug("Checksum check: '" + builder.toString() + "' == '" + checksum + "'?"); | ||||||
| 			return builder.toString().equals(checksum); | 			return builder.toString().equals(checksum); | ||||||
| 		} catch (IOException e) { | 		} catch (IOException e) { | ||||||
| 			e.printStackTrace(); | 			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