Skip to content

Commit d2247e9

Browse files
committed
perf: cache CodeDom assembly paths
1 parent 6f4c812 commit d2247e9

2 files changed

Lines changed: 58 additions & 1 deletion

File tree

MCPForUnity/Editor/Tools/ExecuteCode.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,13 @@ public static class ExecuteCode
3030

3131
private static readonly List<HistoryEntry> _history = new List<HistoryEntry>();
3232
private static string[] _cachedAssemblyPaths;
33+
private static string[] _cachedCodeDomAssemblyPaths;
3334

3435
[UnityEditor.InitializeOnLoadMethod]
3536
private static void OnDomainReload()
3637
{
3738
_cachedAssemblyPaths = null;
39+
_cachedCodeDomAssemblyPaths = null;
3840
RoslynCompiler.ResetCache();
3941
}
4042

@@ -342,6 +344,10 @@ private static Assembly CodeDomCompile(string source, string[] assemblyPaths, ou
342344

343345
internal static string[] FilterAssemblyPathsForCodeDom(string[] allPaths)
344346
{
347+
var useCache = ReferenceEquals(allPaths, _cachedAssemblyPaths);
348+
if (useCache && _cachedCodeDomAssemblyPaths != null)
349+
return _cachedCodeDomAssemblyPaths;
350+
345351
var hasNetstandard = allPaths.Any(p =>
346352
string.Equals(Path.GetFileNameWithoutExtension(p), "netstandard", StringComparison.OrdinalIgnoreCase));
347353

@@ -350,7 +356,10 @@ internal static string[] FilterAssemblyPathsForCodeDom(string[] allPaths)
350356
!_codedomDuplicateAssemblies.Contains(Path.GetFileNameWithoutExtension(p))).ToArray()
351357
: allPaths;
352358

353-
return DeduplicateAssemblyPathsForCodeDom(filtered);
359+
var result = DeduplicateAssemblyPathsForCodeDom(filtered);
360+
if (useCache)
361+
_cachedCodeDomAssemblyPaths = result;
362+
return result;
354363
}
355364

356365
private static string[] DeduplicateAssemblyPathsForCodeDom(string[] paths)

TestProjects/UnityMCPTests/Assets/Tests/EditMode/Tools/ExecuteCodeTests.cs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.CodeDom.Compiler;
33
using System.IO;
44
using System.Linq;
5+
using System.Reflection;
56
using Microsoft.CSharp;
67
using Newtonsoft.Json.Linq;
78
using NUnit.Framework;
@@ -425,6 +426,53 @@ public void FilterAssemblyPathsForCodeDom_DuplicateNames_PrefersReferencedVersio
425426
}
426427
}
427428

429+
[Test]
430+
public void FilterAssemblyPathsForCodeDom_CachedAssemblyPaths_ReusesResultUntilDomainReload()
431+
{
432+
var tempRoot = CreateTempDirectory();
433+
var cachedAssemblyPathsField = typeof(ExecuteCode).GetField(
434+
"_cachedAssemblyPaths",
435+
BindingFlags.NonPublic | BindingFlags.Static);
436+
var cachedCodeDomAssemblyPathsField = typeof(ExecuteCode).GetField(
437+
"_cachedCodeDomAssemblyPaths",
438+
BindingFlags.NonPublic | BindingFlags.Static);
439+
var onDomainReload = typeof(ExecuteCode).GetMethod(
440+
"OnDomainReload",
441+
BindingFlags.NonPublic | BindingFlags.Static);
442+
Assert.IsNotNull(cachedAssemblyPathsField);
443+
Assert.IsNotNull(cachedCodeDomAssemblyPathsField);
444+
Assert.IsNotNull(onDomainReload);
445+
446+
try
447+
{
448+
onDomainReload.Invoke(null, null);
449+
var assemblyName = "McpCodeDomCache" + Guid.NewGuid().ToString("N");
450+
var olderPath = CompileVersionedAssembly(tempRoot, assemblyName, "1.0.0.0");
451+
var newerPath = CompileVersionedAssembly(tempRoot, assemblyName, "2.0.0.0");
452+
var cachedAssemblyPaths = new[] { olderPath, newerPath };
453+
cachedAssemblyPathsField.SetValue(null, cachedAssemblyPaths);
454+
455+
var first = ExecuteCode.FilterAssemblyPathsForCodeDom(cachedAssemblyPaths);
456+
Assert.AreEqual(1, first.Length);
457+
458+
File.WriteAllText(olderPath, "invalidated");
459+
File.WriteAllText(newerPath, "invalidated");
460+
var second = ExecuteCode.FilterAssemblyPathsForCodeDom(cachedAssemblyPaths);
461+
Assert.AreSame(first, second);
462+
463+
onDomainReload.Invoke(null, null);
464+
cachedAssemblyPathsField.SetValue(null, cachedAssemblyPaths);
465+
var afterReload = ExecuteCode.FilterAssemblyPathsForCodeDom(cachedAssemblyPaths);
466+
Assert.AreNotSame(first, afterReload);
467+
Assert.AreEqual(2, afterReload.Length);
468+
}
469+
finally
470+
{
471+
onDomainReload.Invoke(null, null);
472+
Directory.Delete(tempRoot, true);
473+
}
474+
}
475+
428476
// ──────────────────── Helpers ────────────────────
429477

430478
private static string CreateTempDirectory()

0 commit comments

Comments
 (0)