From 4d5d57a4f65b5632b0442c42cf6fa36b11919ce9 Mon Sep 17 00:00:00 2001 From: Miepee Date: Thu, 1 Aug 2024 18:33:57 +0200 Subject: [PATCH] make decoupleItemsFromLocations use less allocations --- BenchmarkTest/BenchmarkTest.csproj | 18 +++++++ BenchmarkTest/DecompileBenchmark.cs | 41 +++++++++++++++ BenchmarkTest/Program.cs | 7 +++ .../patches/DecoupleItemsFromLocations.cs | 52 +++++++++---------- diff.txt | 40 ++++++++++++++ 5 files changed, 132 insertions(+), 26 deletions(-) create mode 100644 BenchmarkTest/BenchmarkTest.csproj create mode 100644 BenchmarkTest/DecompileBenchmark.cs create mode 100644 BenchmarkTest/Program.cs create mode 100644 diff.txt diff --git a/BenchmarkTest/BenchmarkTest.csproj b/BenchmarkTest/BenchmarkTest.csproj new file mode 100644 index 0000000..f569f93 --- /dev/null +++ b/BenchmarkTest/BenchmarkTest.csproj @@ -0,0 +1,18 @@ + + + + Exe + net6.0 + enable + enable + + + + + + + + + + + diff --git a/BenchmarkTest/DecompileBenchmark.cs b/BenchmarkTest/DecompileBenchmark.cs new file mode 100644 index 0000000..e83979f --- /dev/null +++ b/BenchmarkTest/DecompileBenchmark.cs @@ -0,0 +1,41 @@ +using BenchmarkDotNet.Attributes; +using UndertaleModLib; +using UndertaleModLib.Decompiler; +using UndertaleModLib.Models; + +namespace BenchmarkTest; + +[MemoryDiagnoser] +public class DecompileBenchmark +{ + public UndertaleData data; + public GlobalDecompileContext decompileContext; + + [GlobalSetup] + public void GlobalSetup() + { + using (FileStream fs = new FileInfo(@"/home/narr/Dokumente/am2r 1.5.5/assets/game.unx_older").OpenRead()) + { + data = UndertaleIO.Read(fs); + } + decompileContext = new GlobalDecompileContext(data, false); + } + + [Benchmark] + public void AppendVariableToEveryEntry() + { + void AppendGML(UndertaleCode code, string appendedText) + { + var codeText = Decompiler.Decompile(code, decompileContext); + codeText = codeText + appendedText + "\n"; + code.ReplaceGML(codeText, data); + } + + foreach (UndertaleCode codeentry in data.Code.SkipLast((int)(data.Code.Count * 0.99))) + { + if (codeentry.Name.Content == "gml_Object_oRm_a5c11lock_Collision_267") continue; + + AppendGML(codeentry, "var this_variable_is_not_used_and_thus_completely_uselesss = 1; if (!this_variable_is_not_used_and_thus_completely_uselesss) this_variable_is_not_used_and_thus_completely_uselesss = 1"); + } + } +} diff --git a/BenchmarkTest/Program.cs b/BenchmarkTest/Program.cs new file mode 100644 index 0000000..334df3d --- /dev/null +++ b/BenchmarkTest/Program.cs @@ -0,0 +1,7 @@ +// See https://aka.ms/new-console-template for more information + +using BenchmarkDotNet.Running; +using BenchmarkTest; + +Console.WriteLine("Hello, World!"); +BenchmarkRunner.Run(); diff --git a/YAMS-LIB/patches/DecoupleItemsFromLocations.cs b/YAMS-LIB/patches/DecoupleItemsFromLocations.cs index 4b8d386..b2ff875 100644 --- a/YAMS-LIB/patches/DecoupleItemsFromLocations.cs +++ b/YAMS-LIB/patches/DecoupleItemsFromLocations.cs @@ -38,31 +38,31 @@ public static void Apply(UndertaleData gmData, GlobalDecompileContext decompileC gmData.Code.ByName(code).ReplaceGMLInCode("global.item[0]", "global.hasBombs"); } - UndertaleGameObject? elderSeptogg = gmData.GameObjects.ByName("oElderSeptogg"); + const string elderSeptoggName = "oElderSeptogg"; foreach (var gameObject in new[] { - gmData.Rooms.ByName("rm_a0h11").GameObjects.First(go => go.X == 480 && go.Y == 768 && go.ObjectDefinition.Name.Content == elderSeptogg.Name.Content), - gmData.Rooms.ByName("rm_a0h25").GameObjects.First(go => go.X == 120 && go.Y == 816 && go.ObjectDefinition.Name.Content == elderSeptogg.Name.Content), - gmData.Rooms.ByName("rm_a0h25").GameObjects.First(go => go.X == 168 && go.Y == 256 && go.ObjectDefinition.Name.Content == elderSeptogg.Name.Content), - gmData.Rooms.ByName("rm_a0h29").GameObjects.First(go => go.X == 384 && go.Y == 312 && go.ObjectDefinition.Name.Content == elderSeptogg.Name.Content), - gmData.Rooms.ByName("rm_a1h05").GameObjects.First(go => go.X == 1184 && go.Y == 832 && go.ObjectDefinition.Name.Content == elderSeptogg.Name.Content), - gmData.Rooms.ByName("rm_a3h04").GameObjects.First(go => go.X == 528 && go.Y == 1344 && go.ObjectDefinition.Name.Content == elderSeptogg.Name.Content), - gmData.Rooms.ByName("rm_a3h04").GameObjects.First(go => go.X == 1728 && go.Y == 1248 && go.ObjectDefinition.Name.Content == elderSeptogg.Name.Content), - gmData.Rooms.ByName("rm_a3a07").GameObjects.First(go => go.X == 112 && go.Y == 240 && go.ObjectDefinition.Name.Content == elderSeptogg.Name.Content), - gmData.Rooms.ByName("rm_a3b02").GameObjects.First(go => go.X == 192 && go.Y == 896 && go.ObjectDefinition.Name.Content == elderSeptogg.Name.Content), - gmData.Rooms.ByName("rm_a3b08").GameObjects.First(go => go.X == 224 && go.Y == 352 && go.ObjectDefinition.Name.Content == elderSeptogg.Name.Content), - gmData.Rooms.ByName("rm_a0h17").GameObjects.First(go => go.X == 96 && go.Y == 352 && go.ObjectDefinition.Name.Content == elderSeptogg.Name.Content), - gmData.Rooms.ByName("rm_a4b02a").GameObjects.First(go => go.X == 120 && go.Y == 816 && go.ObjectDefinition.Name.Content == elderSeptogg.Name.Content), - gmData.Rooms.ByName("rm_a4b10").GameObjects.First(go => go.X == 144 && go.Y == 624 && go.ObjectDefinition.Name.Content == elderSeptogg.Name.Content), - gmData.Rooms.ByName("rm_a4b10").GameObjects.First(go => go.X == 512 && go.Y == 256 && go.ObjectDefinition.Name.Content == elderSeptogg.Name.Content), - gmData.Rooms.ByName("rm_a4b11").GameObjects.First(go => go.X == 224 && go.Y == 2288 && go.ObjectDefinition.Name.Content == elderSeptogg.Name.Content), - gmData.Rooms.ByName("rm_a5c13").GameObjects.First(go => go.X == 96 && go.Y == 704 && go.ObjectDefinition.Name.Content == elderSeptogg.Name.Content), - gmData.Rooms.ByName("rm_a5c14").GameObjects.First(go => go.X == 1056 && go.Y == 288 && go.ObjectDefinition.Name.Content == elderSeptogg.Name.Content), - gmData.Rooms.ByName("rm_a5c17").GameObjects.First(go => go.X == 192 && go.Y == 288 && go.ObjectDefinition.Name.Content == elderSeptogg.Name.Content), - gmData.Rooms.ByName("rm_a5c18").GameObjects.First(go => go.X == 128 && go.Y == 192 && go.ObjectDefinition.Name.Content == elderSeptogg.Name.Content), - gmData.Rooms.ByName("rm_a5c18").GameObjects.First(go => go.X == 480 && go.Y == 192 && go.ObjectDefinition.Name.Content == elderSeptogg.Name.Content), - gmData.Rooms.ByName("rm_a5c21").GameObjects.First(go => go.X == 160 && go.Y == 384 && go.ObjectDefinition.Name.Content == elderSeptogg.Name.Content), - gmData.Rooms.ByName("rm_a5c21").GameObjects.First(go => go.X == 96 && go.Y == 560 && go.ObjectDefinition.Name.Content == elderSeptogg.Name.Content), + gmData.Rooms.ByName("rm_a0h11").GameObjects.First(go => go.X == 480 && go.Y == 768 && go.ObjectDefinition.Name.Content == elderSeptoggName), + gmData.Rooms.ByName("rm_a0h25").GameObjects.First(go => go.X == 120 && go.Y == 816 && go.ObjectDefinition.Name.Content == elderSeptoggName), + gmData.Rooms.ByName("rm_a0h25").GameObjects.First(go => go.X == 168 && go.Y == 256 && go.ObjectDefinition.Name.Content == elderSeptoggName), + gmData.Rooms.ByName("rm_a0h29").GameObjects.First(go => go.X == 384 && go.Y == 312 && go.ObjectDefinition.Name.Content == elderSeptoggName), + gmData.Rooms.ByName("rm_a1h05").GameObjects.First(go => go.X == 1184 && go.Y == 832 && go.ObjectDefinition.Name.Content == elderSeptoggName), + gmData.Rooms.ByName("rm_a3h04").GameObjects.First(go => go.X == 528 && go.Y == 1344 && go.ObjectDefinition.Name.Content == elderSeptoggName), + gmData.Rooms.ByName("rm_a3h04").GameObjects.First(go => go.X == 1728 && go.Y == 1248 && go.ObjectDefinition.Name.Content == elderSeptoggName), + gmData.Rooms.ByName("rm_a3a07").GameObjects.First(go => go.X == 112 && go.Y == 240 && go.ObjectDefinition.Name.Content == elderSeptoggName), + gmData.Rooms.ByName("rm_a3b02").GameObjects.First(go => go.X == 192 && go.Y == 896 && go.ObjectDefinition.Name.Content == elderSeptoggName), + gmData.Rooms.ByName("rm_a3b08").GameObjects.First(go => go.X == 224 && go.Y == 352 && go.ObjectDefinition.Name.Content == elderSeptoggName), + gmData.Rooms.ByName("rm_a0h17").GameObjects.First(go => go.X == 96 && go.Y == 352 && go.ObjectDefinition.Name.Content == elderSeptoggName), + gmData.Rooms.ByName("rm_a4b02a").GameObjects.First(go => go.X == 120 && go.Y == 816 && go.ObjectDefinition.Name.Content == elderSeptoggName), + gmData.Rooms.ByName("rm_a4b10").GameObjects.First(go => go.X == 144 && go.Y == 624 && go.ObjectDefinition.Name.Content == elderSeptoggName), + gmData.Rooms.ByName("rm_a4b10").GameObjects.First(go => go.X == 512 && go.Y == 256 && go.ObjectDefinition.Name.Content == elderSeptoggName), + gmData.Rooms.ByName("rm_a4b11").GameObjects.First(go => go.X == 224 && go.Y == 2288 && go.ObjectDefinition.Name.Content == elderSeptoggName), + gmData.Rooms.ByName("rm_a5c13").GameObjects.First(go => go.X == 96 && go.Y == 704 && go.ObjectDefinition.Name.Content == elderSeptoggName), + gmData.Rooms.ByName("rm_a5c14").GameObjects.First(go => go.X == 1056 && go.Y == 288 && go.ObjectDefinition.Name.Content == elderSeptoggName), + gmData.Rooms.ByName("rm_a5c17").GameObjects.First(go => go.X == 192 && go.Y == 288 && go.ObjectDefinition.Name.Content == elderSeptoggName), + gmData.Rooms.ByName("rm_a5c18").GameObjects.First(go => go.X == 128 && go.Y == 192 && go.ObjectDefinition.Name.Content == elderSeptoggName), + gmData.Rooms.ByName("rm_a5c18").GameObjects.First(go => go.X == 480 && go.Y == 192 && go.ObjectDefinition.Name.Content == elderSeptoggName), + gmData.Rooms.ByName("rm_a5c21").GameObjects.First(go => go.X == 160 && go.Y == 384 && go.ObjectDefinition.Name.Content == elderSeptoggName), + gmData.Rooms.ByName("rm_a5c21").GameObjects.First(go => go.X == 96 && go.Y == 560 && go.ObjectDefinition.Name.Content == elderSeptoggName), }) { gameObject.CreationCode.ReplaceGMLInCode("global.item[0]", "global.hasBombs"); @@ -77,7 +77,7 @@ public static void Apply(UndertaleData gmData, GlobalDecompileContext decompileC subscreenMenuStep.ReplaceGMLInCode("global.item[2] == 0", "!global.hasSpiderball"); foreach (UndertaleCode code in gmData.Code.Where(c => (c.Name.Content.StartsWith("gml_Script_scr_septoggs_") && c.Name.Content.Contains('2')) || - c.Name.Content == gmData.Rooms.ByName("rm_a0h25").GameObjects.First(go => go.X == 120 && go.Y == 816 && go.ObjectDefinition.Name.Content == elderSeptogg.Name.Content).CreationCode.Name.Content) + c.Name.Content == gmData.Rooms.ByName("rm_a0h25").GameObjects.First(go => go.X == 120 && go.Y == 816 && go.ObjectDefinition.Name.Content == elderSeptoggName).CreationCode.Name.Content) ) { code.ReplaceGMLInCode("global.item[2]", "global.hasSpiderball"); @@ -95,7 +95,7 @@ public static void Apply(UndertaleData gmData, GlobalDecompileContext decompileC foreach (UndertaleCode? code in gmData.Code.Where(c => (c.Name.Content.StartsWith("gml_Script_scr_septoggs_") && c.Name.Content.Contains('4')) || c.Name.Content == "gml_Room_rm_a3b08_Create" || - c == gmData.Rooms.ByName("rm_a5c17").GameObjects.First(go => go.X == 192 && go.Y == 288 && go.ObjectDefinition.Name.Content == elderSeptogg.Name.Content).CreationCode) + c == gmData.Rooms.ByName("rm_a5c17").GameObjects.First(go => go.X == 192 && go.Y == 288 && go.ObjectDefinition.Name.Content == elderSeptoggName).CreationCode) ) { code.ReplaceGMLInCode("global.item[4]", "global.hasHijump"); @@ -120,7 +120,7 @@ public static void Apply(UndertaleData gmData, GlobalDecompileContext decompileC foreach (UndertaleCode? code in gmData.Code.Where(c => (c.Name.Content.StartsWith("gml_Script_scr_septoggs_") && c.Name.Content.Contains('6')) || gmData.Rooms.ByName("rm_a5a03").GameObjects.Where(go => go.X is >= 96 and <= 112 && go.Y is >= 240 and <= 288 && go.ObjectDefinition.Name.Content == "oBlockStep").Select(go => go.CreationCode).Contains(c) || - c == gmData.Rooms.ByName("rm_a0h25").GameObjects.First(go => go.X == 120 && go.Y == 816 && go.ObjectDefinition.Name.Content == elderSeptogg.Name.Content).CreationCode) + c == gmData.Rooms.ByName("rm_a0h25").GameObjects.First(go => go.X == 120 && go.Y == 816 && go.ObjectDefinition.Name.Content == elderSeptoggName).CreationCode) ) { code.ReplaceGMLInCode("global.item[6]", "global.hasSpacejump"); diff --git a/diff.txt b/diff.txt new file mode 100644 index 0000000..1a17044 --- /dev/null +++ b/diff.txt @@ -0,0 +1,40 @@ +diff --git a/UndertaleModLib/Compiler/Compiler.cs b/UndertaleModLib/Compiler/Compiler.cs +index 3fa2ae6b..72e3d7c9 100644 +--- a/UndertaleModLib/Compiler/Compiler.cs ++++ b/UndertaleModLib/Compiler/Compiler.cs +@@ -142,8 +142,11 @@ namespace UndertaleModLib.Compiler + for (int i = 0; i < list.Count; i++) + { + string name = list[i].Name?.Content; +- if (name != null) +- assetIds[name] = i; ++ if (name is not null) ++ { ++ assetIds.Add(name, i); ++ } ++ //assetIds[name] = i; + } + } + } +@@ -154,6 +157,8 @@ namespace UndertaleModLib.Compiler + public delegate void MainThreadFunc(); + public delegate void MainThreadDelegate(MainThreadFunc f); + ++ private static Dictionary codeToContextMapping = new Dictionary(); ++ + // A simple matching convenience + public static bool In(this T obj, params T[] args) + { +@@ -169,7 +174,11 @@ namespace UndertaleModLib.Compiler + + public static CompileContext CompileGMLText(string input, UndertaleData data, UndertaleCode code) + { +- return CompileGMLText(input, new CompileContext(data, code)); ++ bool isInMapping = codeToContextMapping.TryGetValue(data, out CompileContext ctx); ++ var returnedContext = CompileGMLText(input, ctx ?? new CompileContext(data, code)); ++ if (!isInMapping) ++ codeToContextMapping.Add(data, returnedContext); ++ return returnedContext; + } + + public static CompileContext CompileGMLText(string input, CompileContext context, bool redoAssets = false)