diff --git a/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.Predicates.cs b/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.Predicates.cs index 7270c301..a73796ef 100644 --- a/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.Predicates.cs +++ b/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.Predicates.cs @@ -310,8 +310,17 @@ bool IsIncludedFileOrLocation(Cursor cursor, CXFile file, CXSourceLocation locat // Use case insensitive comparison on Windows var equalityComparer = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? StringComparer.OrdinalIgnoreCase : StringComparer.Ordinal; - // Normalize paths to be '/' for comparison - var fileName = file.Name.ToString().NormalizePath(); + // Normalize paths to be '/' for comparison. The same file recurs for + // every cursor it contains, so cache the normalized names per file to + // avoid re-allocating them (and re-running Path.GetFullPath) each call. + if (!_fileNames.TryGetValue(file, out var names)) + { + var name = file.Name.ToString().NormalizePath(); + names = (name, name.NormalizeFullPath()); + _fileNames.Add(file, names); + } + + var fileName = names.Name; if (_visitedFiles.Add(fileName) && _config.LogVisitedFiles) { @@ -322,7 +331,7 @@ bool IsIncludedFileOrLocation(Cursor cursor, CXFile file, CXSourceLocation locat { return true; } - else if (_config.TraversalNames.Contains(fileName.NormalizeFullPath(), equalityComparer)) + else if (_config.TraversalNames.Contains(names.FullName, equalityComparer)) { return true; } diff --git a/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.cs b/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.cs index 87bc0e58..08bdcb7d 100644 --- a/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.cs +++ b/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.cs @@ -63,6 +63,7 @@ public sealed partial class PInvokeGenerator : IDisposable private readonly Dictionary> _topLevelClassUsings; private readonly Dictionary> _topLevelClassAttributes; private readonly Dictionary _fileContents; + private readonly Dictionary _fileNames; private readonly HashSet _topLevelClassNames; private readonly HashSet _usedRemappings; private readonly string _placeholderMacroType; @@ -161,6 +162,7 @@ public PInvokeGenerator(PInvokeGeneratorConfiguration config, Func(StringComparer.Ordinal); _topLevelClassAttributes = new Dictionary>(StringComparer.Ordinal); _fileContents = []; + _fileNames = []; _topLevelClassUsings = new Dictionary>(StringComparer.Ordinal); _usedRemappings = new HashSet(StringComparer.Ordinal); _filePath = ""; @@ -1680,6 +1682,7 @@ public void GenerateBindings(TranslationUnit translationUnit, string filePath, s _overloadIndices.Clear(); _isExcluded.Clear(); _fileContents.Clear(); + _fileNames.Clear(); if (translationUnit.Handle.NumDiagnostics != 0) {