Skip to content

Add MSBuild.Benchmarks and greatly improve ItemSpecModifiers and BuiltInMetadata performance#13386

Merged
SimaTian merged 10 commits intomainfrom
dev/dustinca/itemspecmodifiers-perf
Mar 24, 2026
Merged

Add MSBuild.Benchmarks and greatly improve ItemSpecModifiers and BuiltInMetadata performance#13386
SimaTian merged 10 commits intomainfrom
dev/dustinca/itemspecmodifiers-perf

Conversation

@DustinCampbell
Copy link
Copy Markdown
Member

I recommend reviewing this pull request commit-by-commit.

Summary of Changes

  • Introduce new MSBuild.Benchmarks project for tackling performance investigations.
  • Add a few benchmarks for various methods on ItemSpecModifiers.
  • Make several performance fixes related to ItemSpecModifiers and BuildInMetadata.
  • General clean up.

Across the board, most benchmarks are 3×–35× faster with allocations eliminated or reduced by 93–100%. The largest wins are in repeated-access and multi-item scenarios, which are the most representative of real build workloads. The full details are below but here are the highlights.

Highlights

🚀 Speed Improvements (.NET 10.0)

Benchmark Before After Speedup
IsItemSpecModifier_AllModifiers 151.4 ns 38.5 ns 3.9×
GetItemSpecModifier_DefiningProjectDirectory 812.2 ns 72.4 ns 11.2×
TaskItem_AllDerivableModifiers_Once 434.5 ns 87.4 ns 5.0×
TaskItem_FilenameAndExtension_Repeated 908.5 ns 173.7 ns 5.2×
TaskItem_Filename_ManyItems 9,651 ns 1,857 ns 5.2×
TaskItem_FullPathDerivedModifiers_Repeated 2,128 ns 321.6 ns 6.6×
TaskItem_DefiningProjectDirectory_Repeated 9,121 ns 970.8 ns 9.4×
PI_DefiningProjectDirectory_Repeated 9,092 ns 1,021 ns 8.9×
PI_DefiningProjectFullPath_AllItems_Multi 35,245 ns 9,947 ns 3.5×
PI_DefiningProjectDir_AllItems_Multi_Repeated 878,931 ns 103,961 ns 8.5×
PI_FilenameExtension_AllItems 22,698 ns 5,343 ns 4.2×
PI_FilenameExtension_AllItems_Repeated 181,612 ns 67,028 ns 2.7×

🧹 Allocation Reductions (.NET 10.0)

Benchmark Before After Reduction
TaskItem_AllDerivableModifiers_Once 1,232 B 0 B 100%
TaskItem_FilenameAndExtension_Repeated 640 B 0 B 100%
TaskItem_Filename_ManyItems 7,920 B 0 B 100%
TaskItem_FullPathDerivedModifiers_Repeated 7,120 B 0 B 100%
TaskItem_DefiningProjectDirectory_Repeated 8,240 B 0 B 100%
TaskItem_AllDefiningProjectModifiers_Once 912 B 0 B 100%
TaskItem_DefiningProjectNameExtension_AllItems 8,800 B 0 B 100%
GetItemSpecModifier_DefiningProjectDirectory 536 B 0 B 100%
PI_FilenameExtension_AllItems_Repeated 143,840 B 640 B 99.6%
PI_DefiningProjectDir_AllItems_Multi_Repeated 824,640 B 640 B 99.9%
PI_FilenameExtension_AllItems 14,384 B 64 B 99.6%
PI_DefiningProjectDirectory_Repeated 8,304 B 64 B 99.2%
PI_AllDerivableModifiers_Once 1,296 B 64 B 95.1%
PI_AllDefiningProjectModifiers_Once 976 B 64 B 93.4%

📊 .NET Framework 4.8.1

Benchmark Before After Speedup
GetItemSpecModifier_DefiningProjectDirectory 5,467 ns 156.8 ns 34.9×
TaskItem_DefiningProjectDirectory_Repeated 58,025 ns 2,539 ns 22.9×
PI_DefiningProjectDir_AllItems_Multi_Repeated 6,399 μs 282.3 μs 22.7×
TaskItem_Filename_ManyItems 110,078 ns 6,916 ns 15.9×
TaskItem_FullPathDerivedModifiers_Repeated 26,619 ns 2,262 ns 11.8×
PI_FilenameExtension_AllItems_Repeated 2,162 μs 202.6 μs 10.7×
TaskItem_AllDerivableModifiers_Once 5,322 ns 507.2 ns 10.5×
PI_FilenameExtension_AllItems 216,406 ns 20,366 ns 10.6×
TaskItem_FilenameAndExtension_Repeated 10,238 ns 664.7 ns 15.4×
PI_AllDerivableModifiers_Once 5,525 ns 688.6 ns 8.0×
PI_DefiningProjectDirectory_Repeated 64,204 ns 2,796 ns 23.0×
PI_AllDefiningProjectModifiers_Once 9,808 ns 1,154 ns 8.5×
TaskItem_AllDefiningProjectModifiers_Once 8,636 ns 965.3 ns 8.9×

'Quick-and-Dirty' Telemetry

I had Copilot write some "quick-and-dirty" telemetry to track information in ItemSpecModifiers and dump it to a file. I built MSBuild with that extra telemetry and then built Roslyn (starting from Microsoft.VisualStudio.LanguageServices.CSharp.csproj) using that MSBuild. This gave me a dump with loads of interesting details. For example, IsItemSpecModifier was called 901,057 times.

Full Quick-and-Dirty Telemetry Dump
=== ItemSpecModifiers Telemetry (2026-03-12T09:38:41.0365991-07:00) ===

--- Top-level method calls ---
  IsItemSpecModifier:            901,057
  IsDerivableItemSpecModifier:   144,857
  GetItemSpecModifier:           180,890

--- Compute helper calls ---
  ComputeFullPath:     75,443
  ComputeRootDir:      84
  ComputeFilename:     57,426
  ComputeExtension:    32,071
  ComputeRelativeDir:  22
  ComputeDirectory:    84
  ComputeModifiedTime: 0
  ComputeCreatedTime:  0
  ComputeAccessedTime: 0

--- Per-modifier breakdown (inside GetItemSpecModifier) ---
  FullPath:                    44,783
  RootDir:                     41
  Filename:                    57,426
  Extension:                   6,462
  RelativeDir:                 22
  Directory:                   41
  RecursiveDir:                0
  Identity:                    15,814
  ModifiedTime:                0
  CreatedTime:                 0
  AccessedTime:                0
  DefiningProjectFullPath:     30,535
  DefiningProjectDirectory:    43
  DefiningProjectName:         0
  DefiningProjectExtension:    25,609

==========================================================
  Per-ItemSpec Modifier Hit Matrix
==========================================================

  Unique item specs seen:       13,809
  Item specs hit > 1 time:      13,005
  Grand total modifier lookups: 180,890

--- Top 50 hottest item specs (by total modifier calls) ---

  #1 (1,502 calls): System.Runtime.CompilerServices.InternalsVisibleTo
      Identity                              751
      DefiningProjectFullPath               751

  #2 (380 calls): D:\Projects\roslyn\artifacts\bin\Microsoft.CodeAnalysis\Debug\netstandard2.0\Microsoft.CodeAnalysis.dll
      FullPath                               17
      Filename                              280
      Extension                              40
      Identity                               21
      DefiningProjectFullPath                22

  #3 (270 calls): D:\Projects\roslyn\artifacts\bin\Microsoft.CodeAnalysis.Scripting\Debug\netstandard2.0\Microsoft.CodeAnalysis.Scripting.dll
      FullPath                               12
      Filename                              195
      Extension                              30
      Identity                               16
      DefiningProjectFullPath                17

  #4 (270 calls): D:\Projects\roslyn\artifacts\bin\Microsoft.CodeAnalysis.Workspaces\Debug\netstandard2.0\Microsoft.CodeAnalysis.Workspaces.dll
      FullPath                               12
      Filename                              195
      Extension                              30
      Identity                               16
      DefiningProjectFullPath                17

  #5 (247 calls): D:\.nuget\packages\system.threading.tasks.extensions\4.6.3\lib\netstandard2.0\System.Threading.Tasks.Extensions.dll
      FullPath                               13
      Filename                              221
      Identity                               13

  #6 (247 calls): D:\.nuget\packages\system.memory\4.6.3\lib\netstandard2.0\System.Memory.dll
      FullPath                               13
      Filename                              221
      Identity                               13

  #7 (247 calls): D:\.nuget\packages\system.buffers\4.6.1\lib\netstandard2.0\System.Buffers.dll
      FullPath                               13
      Filename                              221
      Identity                               13

  #8 (247 calls): D:\.nuget\packages\system.numerics.vectors\4.6.1\lib\netstandard2.0\System.Numerics.Vectors.dll
      FullPath                               13
      Filename                              221
      Identity                               13

  #9 (247 calls): D:\.nuget\packages\system.text.encoding.codepages\8.0.0\lib\netstandard2.0\System.Text.Encoding.CodePages.dll
      FullPath                               13
      Filename                              221
      Identity                               13

  #10 (247 calls): D:\.nuget\packages\system.runtime.compilerservices.unsafe\6.1.2\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll
      FullPath                               13
      Filename                              221
      Identity                               13

  #11 (245 calls): D:\.nuget\packages\microsoft.dotnet.arcade.sdk\10.0.0-beta.26160.1\tools\Assets\DotNetPackageIcon.png
      FullPath                               48
      Filename                               40
      Extension                              70
      Identity                                2
      DefiningProjectFullPath                37
      DefiningProjectDirectory                8
      DefiningProjectExtension               40

  #12 (245 calls): D:\Projects\roslyn\eng\targets\..\..\src\NuGet\ThirdPartyNotices.rtf
      FullPath                               48
      Filename                               40
      Extension                              70
      Identity                                2
      DefiningProjectFullPath                37
      DefiningProjectDirectory                8
      DefiningProjectExtension               40

  #13 (240 calls): D:\.nuget\packages\system.collections.immutable\10.0.1\lib\netstandard2.0\System.Collections.Immutable.dll
      FullPath                               12
      Filename                              216
      Identity                               12

  #14 (240 calls): D:\.nuget\packages\system.reflection.metadata\10.0.1\lib\netstandard2.0\System.Reflection.Metadata.dll
      FullPath                               12
      Filename                              216
      Identity                               12

  #15 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Web.dll
      FullPath                               13
      Filename                              208
      Identity                               13

  #16 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Threading.ThreadPool.dll
      FullPath                               13
      Filename                              208
      Identity                               13

  #17 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.IO.FileSystem.Watcher.dll
      FullPath                               13
      Filename                              208
      Identity                               13

  #18 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Resources.ResourceManager.dll
      FullPath                               13
      Filename                              208
      Identity                               13

  #19 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.IO.dll
      FullPath                               13
      Filename                              208
      Identity                               13

  #20 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.IO.Pipes.dll
      FullPath                               13
      Filename                              208
      Identity                               13

  #21 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.IO.MemoryMappedFiles.dll
      FullPath                               13
      Filename                              208
      Identity                               13

  #22 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.ValueTuple.dll
      FullPath                               13
      Filename                              208
      Identity                               13

  #23 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Console.dll
      FullPath                               13
      Filename                              208
      Identity                               13

  #24 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Linq.Parallel.dll
      FullPath                               13
      Filename                              208
      Identity                               13

  #25 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Security.Claims.dll
      FullPath                               13
      Filename                              208
      Identity                               13

  #26 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.IO.UnmanagedMemoryStream.dll
      FullPath                               13
      Filename                              208
      Identity                               13

  #27 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Threading.Overlapped.dll
      FullPath                               13
      Filename                              208
      Identity                               13

  #28 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Drawing.Primitives.dll
      FullPath                               13
      Filename                              208
      Identity                               13

  #29 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Net.WebSockets.dll
      FullPath                               13
      Filename                              208
      Identity                               13

  #30 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Security.Cryptography.Algorithms.dll
      FullPath                               13
      Filename                              208
      Identity                               13

  #31 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.IO.FileSystem.DriveInfo.dll
      FullPath                               13
      Filename                              208
      Identity                               13

  #32 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Diagnostics.Tracing.dll
      FullPath                               13
      Filename                              208
      Identity                               13

  #33 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Linq.Expressions.dll
      FullPath                               13
      Filename                              208
      Identity                               13

  #34 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Security.Principal.dll
      FullPath                               13
      Filename                              208
      Identity                               13

  #35 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Globalization.Calendars.dll
      FullPath                               13
      Filename                              208
      Identity                               13

  #36 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Security.Cryptography.Primitives.dll
      FullPath                               13
      Filename                              208
      Identity                               13

  #37 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.ObjectModel.dll
      FullPath                               13
      Filename                              208
      Identity                               13

  #38 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Xml.XDocument.dll
      FullPath                               13
      Filename                              208
      Identity                               13

  #39 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Collections.dll
      FullPath                               13
      Filename                              208
      Identity                               13

  #40 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.ComponentModel.TypeConverter.dll
      FullPath                               13
      Filename                              208
      Identity                               13

  #41 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Runtime.InteropServices.dll
      FullPath                               13
      Filename                              208
      Identity                               13

  #42 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Collections.Concurrent.dll
      FullPath                               13
      Filename                              208
      Identity                               13

  #43 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Collections.Specialized.dll
      FullPath                               13
      Filename                              208
      Identity                               13

  #44 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Dynamic.Runtime.dll
      FullPath                               13
      Filename                              208
      Identity                               13

  #45 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Net.Requests.dll
      FullPath                               13
      Filename                              208
      Identity                               13

  #46 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Security.Cryptography.X509Certificates.dll
      FullPath                               13
      Filename                              208
      Identity                               13

  #47 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Net.dll
      FullPath                               13
      Filename                              208
      Identity                               13

  #48 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.IO.Compression.ZipFile.dll
      FullPath                               13
      Filename                              208
      Identity                               13

  #49 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Xml.XmlSerializer.dll
      FullPath                               13
      Filename                              208
      Identity                               13

  #50 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Runtime.CompilerServices.VisualC.dll
      FullPath                               13
      Filename                              208
      Identity                               13

--- Repetition histogram (total modifier calls per item spec → count of item specs) ---

     1,502 calls  →         1 item specs
       380 calls  →         1 item specs
       270 calls  →         2 item specs
       247 calls  →         6 item specs
       245 calls  →         2 item specs
       240 calls  →         2 item specs
       234 calls  →       112 item specs
       226 calls  →         1 item specs
       224 calls  →         2 item specs
       204 calls  →         4 item specs
       196 calls  →         1 item specs
       164 calls  →        13 item specs
       160 calls  →         2 item specs
       151 calls  →         3 item specs
       144 calls  →        53 item specs
       140 calls  →         6 item specs
       138 calls  →         4 item specs
       134 calls  →         1 item specs
       132 calls  →         7 item specs
       122 calls  →         2 item specs
       117 calls  →        14 item specs
       113 calls  →       124 item specs
       111 calls  →         1 item specs
       110 calls  →         2 item specs
       109 calls  →         1 item specs
       101 calls  →         3 item specs
       100 calls  →         2 item specs
        99 calls  →         1 item specs
        98 calls  →         1 item specs
        91 calls  →         5 item specs
        89 calls  →        59 item specs
        86 calls  →         2 item specs
        84 calls  →         1 item specs
        82 calls  →         2 item specs
        80 calls  →         7 item specs
        78 calls  →         1 item specs
        76 calls  →         2 item specs
        75 calls  →         1 item specs
        74 calls  →         5 item specs
        73 calls  →         3 item specs
        72 calls  →         2 item specs
        70 calls  →         1 item specs
        66 calls  →         5 item specs
        65 calls  →         5 item specs
        60 calls  →        10 item specs
        58 calls  →         8 item specs
        57 calls  →         1 item specs
        56 calls  →         1 item specs
        54 calls  →         6 item specs
        52 calls  →         3 item specs
        51 calls  →         8 item specs
        50 calls  →         1 item specs
        49 calls  →         2 item specs
        48 calls  →         3 item specs
        47 calls  →         1 item specs
        46 calls  →         1 item specs
        45 calls  →        13 item specs
        44 calls  →        20 item specs
        41 calls  →         2 item specs
        40 calls  →         8 item specs
        39 calls  →         1 item specs
        37 calls  →         4 item specs
        36 calls  →        51 item specs
        35 calls  →         5 item specs
        34 calls  →         1 item specs
        33 calls  →         1 item specs
        32 calls  →         2 item specs
        30 calls  →         4 item specs
        29 calls  →        11 item specs
        28 calls  →        20 item specs
        27 calls  →        11 item specs
        26 calls  →        16 item specs
        24 calls  →        30 item specs
        23 calls  →         3 item specs
        22 calls  →       153 item specs
        21 calls  →         1 item specs
        20 calls  →        26 item specs
        19 calls  →         1 item specs
        18 calls  →       109 item specs
        16 calls  →        30 item specs
        15 calls  →        35 item specs
        14 calls  →       383 item specs
        13 calls  →       166 item specs
        12 calls  →     1,051 item specs
        11 calls  →         1 item specs
        10 calls  →        70 item specs
         9 calls  →        43 item specs
         8 calls  →     7,012 item specs
         7 calls  →        50 item specs
         6 calls  →       910 item specs
         5 calls  →     1,420 item specs
         4 calls  →       449 item specs
         3 calls  →        32 item specs
         2 calls  →       340 item specs
         1 calls  →       804 item specs

Initial Benchmark Results

.NET 10.0

Method Mean Error StdDev Gen0 Allocated
IsItemSpecModifier_AllModifiers 151.425 ns 0.1309 ns 0.1161 ns - -
IsDerivableItemSpecModifier_RecursiveDir 2.522 ns 0.0028 ns 0.0025 ns - -
GetItemSpecModifier_FullPath 267.552 ns 0.3441 ns 0.3050 ns - -
GetItemSpecModifier_Directory 359.023 ns 0.7603 ns 0.6740 ns 0.0224 376 B
GetItemSpecModifier_ModifiedTime 28,544.061 ns 237.0185 ns 221.7073 ns - 176 B
GetItemSpecModifier_DefiningProjectDirectory 812.229 ns 3.3636 ns 2.9817 ns 0.0315 536 B
TaskItem_AllDerivableModifiers_Once 434.5 ns 4.36 ns 4.08 ns 0.0734 1232 B
TaskItem_FilenameAndExtension_Repeated 908.5 ns 1.13 ns 1.00 ns 0.0381 640 B
TaskItem_Filename_ManyItems 9,651.3 ns 29.02 ns 25.72 ns 0.4730 7920 B
TaskItem_FullPathDerivedModifiers_Repeated 2,127.6 ns 7.45 ns 6.60 ns 0.4234 7120 B
ProjectItemInstance_AllDerivableModifiers_Once 513.4 ns 2.93 ns 2.74 ns 0.0772 1296 B
ProjectItemInstance_FilenameExtension_AllItems 22,697.6 ns 68.62 ns 64.19 ns 0.8545 14384 B
ProjectItemInstance_FilenameExtension_AllItems_Repeated 181,612.2 ns 1,125.69 ns 940.00 ns 8.5449 143840 B
ProjectItemInstance_AllDefiningProjectModifiers_Once 1.559 μs 0.0047 μs 0.0040 μs 0.0572 976 B
ProjectItemInstance_DefiningProjectDirectory_Repeated 9.092 μs 0.0654 μs 0.0580 μs 0.4883 8304 B
ProjectItemInstance_DefiningProjectNameExtension_AllItems_SingleProject 12.515 μs 0.0297 μs 0.0263 μs 0.5188 8864 B
ProjectItemInstance_DefiningProjectFullPath_AllItems_MultiProject 35.245 μs 0.0405 μs 0.0379 μs - 64 B
ProjectItemInstance_DefiningProjectDirectory_AllItems_MultiProject_Repeated 878.931 μs 3.1495 μs 2.7919 μs 48.8281 824640 B
TaskItem_AllDefiningProjectModifiers_Once 1.430 μs 0.0027 μs 0.0023 μs 0.0534 912 B
TaskItem_DefiningProjectNameExtension_AllItems 11.628 μs 0.0289 μs 0.0241 μs 0.5188 8800 B
TaskItem_DefiningProjectDirectory_Repeated 9.121 μs 0.0192 μs 0.0170 μs 0.4883 8240 B

.NET Framework 4.8.1

Method Mean Error StdDev Gen0 Allocated
IsItemSpecModifier_AllModifiers 227.45 ns 0.297 ns 0.264 ns - -
IsDerivableItemSpecModifier_RecursiveDir 10.49 ns 0.019 ns 0.018 ns - -
GetItemSpecModifier_FullPath 1,267.45 ns 0.844 ns 0.705 ns - -
GetItemSpecModifier_Directory 2,433.43 ns 7.400 ns 6.560 ns 0.0954 517 B
GetItemSpecModifier_ModifiedTime 41,881.06 ns 111.954 ns 93.487 ns 0.1221 878 B
GetItemSpecModifier_DefiningProjectDirectory 5,467.24 ns 8.295 ns 6.926 ns 0.1602 857 B
TaskItem_AllDerivableModifiers_Once 5.322 μs 0.0354 μs 0.0331 μs 0.3662 1923 B
TaskItem_FilenameAndExtension_Repeated 10.238 μs 0.0108 μs 0.0101 μs 0.1373 761 B
TaskItem_Filename_ManyItems 110.078 μs 0.1367 μs 0.1212 μs 2.3193 12379 B
TaskItem_FullPathDerivedModifiers_Repeated 26.619 μs 0.1695 μs 0.1585 μs 2.1973 11578 B
ProjectItemInstance_AllDerivableModifiers_Once 5.525 μs 0.0311 μs 0.0276 μs 0.3662 1959 B
ProjectItemInstance_FilenameExtension_AllItems 216.406 μs 0.2767 μs 0.2160 μs 2.9297 16422 B
ProjectItemInstance_FilenameExtension_AllItems_Repeated 2,161.623 μs 10.4073 μs 9.2258 μs 31.2500 164225 B
ProjectItemInstance_AllDefiningProjectModifiers_Once 9.808 μs 0.0177 μs 0.0165 μs 0.2594 1418 B
ProjectItemInstance_DefiningProjectDirectory_Repeated 64.204 μs 0.3983 μs 0.3726 μs 2.3193 12616 B
ProjectItemInstance_DefiningProjectNameExtension_AllItems_SingleProject 131.504 μs 0.3383 μs 0.3165 μs 2.1973 12456 B
ProjectItemInstance_DefiningProjectFullPath_AllItems_MultiProject 173.171 μs 0.7242 μs 0.5654 μs - 38 B
ProjectItemInstance_DefiningProjectDirectory_AllItems_MultiProject_Repeated 6,399.063 μs 71.6927 μs 67.0614 μs 234.3750 1242225 B
TaskItem_AllDefiningProjectModifiers_Once 8.636 μs 0.0177 μs 0.0147 μs 0.2594 1382 B
TaskItem_DefiningProjectNameExtension_AllItems 126.982 μs 0.2250 μs 0.2104 μs 2.1973 12420 B
TaskItem_DefiningProjectDirectory_Repeated 58.025 μs 0.1388 μs 0.1299 μs 2.3804 12579 B

Final Benchmark Results

.NET 10.0

Method Mean Error StdDev Gen0 Allocated
IsItemSpecModifier_AllModifiers 38.4923 ns 0.5501 ns 0.5145 ns - -
IsDerivableItemSpecModifier_RecursiveDir 0.0000 ns 0.0000 ns 0.0000 ns - -
GetItemSpecModifier_FullPath 260.1019 ns 0.3623 ns 0.3212 ns - -
GetItemSpecModifier_Directory 413.2121 ns 1.9441 ns 1.8185 ns 0.0224 376 B
GetItemSpecModifier_ModifiedTime 30,272.3116 ns 408.0450 ns 381.6855 ns - 176 B
GetItemSpecModifier_DefiningProjectDirectory 72.3691 ns 0.0289 ns 0.0270 ns - -
TaskItem_AllDerivableModifiers_Once 87.41 ns 0.226 ns 0.200 ns - -
TaskItem_FilenameAndExtension_Repeated 173.68 ns 1.812 ns 1.695 ns - -
TaskItem_Filename_ManyItems 1,856.79 ns 1.128 ns 0.942 ns - -
TaskItem_FullPathDerivedModifiers_Repeated 321.57 ns 0.301 ns 0.267 ns - -
ProjectItemInstance_AllDerivableModifiers_Once 143.78 ns 0.493 ns 0.462 ns 0.0038 64 B
ProjectItemInstance_FilenameExtension_AllItems 5,343.30 ns 4.955 ns 4.138 ns - 64 B
ProjectItemInstance_FilenameExtension_AllItems_Repeated 67,028.30 ns 252.985 ns 224.264 ns - 640 B
ProjectItemInstance_AllDefiningProjectModifiers_Once 459.4 ns 0.34 ns 0.31 ns 0.0038 64 B
ProjectItemInstance_DefiningProjectDirectory_Repeated 1,020.5 ns 0.56 ns 0.47 ns 0.0038 64 B
ProjectItemInstance_DefiningProjectNameExtension_AllItems_SingleProject 20,091.0 ns 17.96 ns 16.80 ns - 64 B
ProjectItemInstance_DefiningProjectFullPath_AllItems_MultiProject 9,946.7 ns 5.28 ns 4.68 ns - 64 B
ProjectItemInstance_DefiningProjectDirectory_AllItems_MultiProject_Repeated 103,960.5 ns 57.74 ns 48.21 ns - 640 B
TaskItem_AllDefiningProjectModifiers_Once 400.5 ns 0.15 ns 0.12 ns - -
TaskItem_DefiningProjectNameExtension_AllItems 19,150.3 ns 11.55 ns 10.24 ns - -
TaskItem_DefiningProjectDirectory_Repeated 970.8 ns 0.62 ns 0.55 ns - -

.NET Framework 4.8.1

Method Mean Error StdDev Gen0 Allocated
IsItemSpecModifier_AllModifiers 106.532 ns 0.4289 ns 0.4012 ns - -
IsDerivableItemSpecModifier_RecursiveDir 5.067 ns 0.0031 ns 0.0024 ns - -
GetItemSpecModifier_FullPath 1,331.138 ns 1.4666 ns 1.3001 ns - -
GetItemSpecModifier_Directory 2,471.887 ns 4.2333 ns 3.7527 ns 0.0954 517 B
GetItemSpecModifier_ModifiedTime 44,773.794 ns 405.2647 ns 359.2566 ns 0.1221 878 B
GetItemSpecModifier_DefiningProjectDirectory 156.840 ns 0.2242 ns 0.1987 ns - -
TaskItem_AllDerivableModifiers_Once 507.2 ns 1.19 ns 1.11 ns - -
TaskItem_FilenameAndExtension_Repeated 664.7 ns 0.39 ns 0.35 ns - -
TaskItem_Filename_ManyItems 6,916.2 ns 4.03 ns 3.77 ns - -
TaskItem_FullPathDerivedModifiers_Repeated 2,261.6 ns 3.34 ns 2.96 ns - -
ProjectItemInstance_AllDerivableModifiers_Once 688.6 ns 1.01 ns 0.94 ns 0.0067 36 B
ProjectItemInstance_FilenameExtension_AllItems 20,366.3 ns 11.28 ns 10.56 ns - 36 B
ProjectItemInstance_FilenameExtension_AllItems_Repeated 202,570.4 ns 271.12 ns 240.34 ns - 362 B
ProjectItemInstance_AllDefiningProjectModifiers_Once 1,153.5 ns 13.83 ns 12.26 ns 0.0057 36 B
ProjectItemInstance_DefiningProjectDirectory_Repeated 2,795.7 ns 17.33 ns 16.21 ns 0.0038 36 B
ProjectItemInstance_DefiningProjectNameExtension_AllItems_SingleProject 46,236.9 ns 105.16 ns 93.22 ns - 36 B
ProjectItemInstance_DefiningProjectFullPath_AllItems_MultiProject 28,362.1 ns 34.50 ns 30.58 ns - 36 B
ProjectItemInstance_DefiningProjectDirectory_AllItems_MultiProject_Repeated 282,316.9 ns 1,944.00 ns 1,818.42 ns - 364 B
TaskItem_AllDefiningProjectModifiers_Once 965.3 ns 5.43 ns 4.53 ns - -
TaskItem_DefiningProjectNameExtension_AllItems 42,707.8 ns 179.84 ns 168.23 ns - -
TaskItem_DefiningProjectDirectory_Repeated 2,539.1 ns 9.64 ns 8.05 ns - -

Copilot AI review requested due to automatic review settings March 13, 2026 20:00
@DustinCampbell DustinCampbell requested a review from a team as a code owner March 13, 2026 20:00
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a new MSBuild.Benchmarks project and refactors item-spec modifier evaluation/caching paths (ItemSpecModifiers, BuiltInMetadata, and item implementations) to significantly reduce repeated computation and allocations in common metadata-access scenarios.

Changes:

  • Add MSBuild.Benchmarks (BenchmarkDotNet-based) and wire it into solution files / ignore BenchmarkDotNet artifacts.
  • Replace single-string FullPath caching with a richer per-item ItemSpecModifiers.Cache, plus a shared cache for DefiningProject* modifiers.
  • Refactor modifier identification to a fast length/character-based classifier (ItemSpecModifierKind) and update call sites/tests accordingly.

Reviewed changes

Copilot reviewed 21 out of 22 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
src/Utilities/TaskItem.cs Switch TaskItem built-in metadata caching from _fullPath to ItemSpecModifiers.Cache.
src/Shared/TaskParameter.cs Update serialized task item metadata retrieval to use ItemSpecModifiers.Cache + kind-based lookup.
src/MSBuild.Benchmarks/readme.md Add benchmark-running documentation.
src/MSBuild.Benchmarks/Program.cs Add benchmark host with custom CLI flags and config wiring.
src/MSBuild.Benchmarks/MSBuild.Benchmarks.csproj New benchmarks project with BenchmarkDotNet references and MSBuild project references.
src/MSBuild.Benchmarks/ItemSpecModifiersCachingBenchmark.cs Add benchmarks focused on per-item caching behavior.
src/MSBuild.Benchmarks/ItemSpecModifiersBenchmark.cs Add benchmarks for modifier classification and single-call modifier computation.
src/MSBuild.Benchmarks/Extensions.cs Add helper extensions for BenchmarkDotNet summary exit codes.
src/MSBuild.Benchmarks/DefiningProjectModifiersBenchmark.cs Add benchmarks for DefiningProject* modifier scenarios (single/multi project).
src/Framework/Properties/AssemblyInfo.cs Add IVT for MSBuild.Benchmarks so it can access internal Framework APIs.
src/Framework/ItemSpecModifiers.cs Major refactor: kind-based modifier classifier, per-item cache struct, and shared defining-project cache.
src/Framework/ItemSpecModifierKind.cs Introduce enum for fast modifier-kind dispatch.
src/Framework.UnitTests/FileUtilities_Tests.cs Update tests to new ItemSpecModifierKind/cache-based APIs.
src/Build/Instance/ProjectMetadataInstance.cs Speed up reserved-name validation using ItemSpecModifiers.IsItemSpecModifier.
src/Build/Instance/ProjectItemInstance.cs Update built-in metadata retrieval + caching to use ItemSpecModifierKind and ItemSpecModifiers.Cache.
src/Build/Evaluation/Expander.cs Update %() transform path to call the new GetItemSpecModifier overload.
src/Build/Definition/ProjectItem.cs Update built-in metadata retrieval/caching to ItemSpecModifiers.Cache.
src/Build/Definition/BuiltInMetadata.cs Refactor built-in metadata access to kind-based dispatch and cache struct.
eng/dependabot/Directory.Packages.props Update/add BenchmarkDotNet package versions for central management.
MSBuild.slnx Add benchmarks project to the solution definition.
MSBuild.Dev.slnf Add benchmarks project to the dev solution filter.
.gitignore Ignore BenchmarkDotNet.Artifacts/ outputs.

- Update BenchmarkDotNet to version: 0.13.12.
- Add BenchmarkDotNet.Diagnostics.Windows package for capturing ETW traces.
- Add project to contain benchmarks written against Microsoft.Build, Microsoft.Build.Framework, Microsoft.Build.Tasks, or Microsoft.Build.Utilities
- Add nullability annotations
- Use string length and starting characters as discriminators to avoid hashing every modifier.
- Reduce complexity of GetItemSpecModifier.
- Don't call GetItemSpecModifier recursively for DefiningProject* modifiers.
Introduce CachedItemSpecModifiers struct to cache derivable modifier
results (FullPath, RootDir, Filename, Extension, RelativeDir, Directory)
per item, replacing the single fullPath cache. This eliminates redundant
Path.GetFileNameWithoutExtension, Path.GetExtension, and similar calls
across repeated metadata accesses on the same item.
DefiningProject* modifiers (FullPath, Directory, Name, Extension) operate on the defining project path, not the item spec. In a typical build there are only ~15 distinct defining projects but tens of thousands of items, so the same ComputeFullPath/ComputeRootDir/ComputeDirectory chain was running redundantly for every item.

Add a ConcurrentDictionary<string, DefiningProjectModifierCache> keyed by the escaped defining project path. All four modifier values are computed eagerly on the first miss and shared across all items from that project. TryGetValue on the hot path avoids closure allocation; the GetOrAdd fallback runs only once per distinct project.
- Extract ModifierKind to a top-level internal enum (ItemSpecModifierKind) and make TryGetModifierKind public so callers can resolve the modifier name once and pass the kind through, eliminating redundant lookups.
- Add TryGetDerivableModifierKind for the common pattern of resolving a modifier while excluding RecursiveDir, and add a GetItemSpecModifier overload that accepts ItemSpecModifierKind directly.
- Update all callers (ProjectItemInstance.TaskItem, ProjectItem, Utilities.TaskItem, TaskParameter, BuiltInMetadata) to resolve once at the entry point and pass the kind through, removing 2-3 redundant TryGetModifierKind calls per metadata access.
Avoids boxing allocations when the array was implicitly cast to ICollection<string> or IEnumerable<string>, and ensures foreach loops use the struct enumerator with zero allocation. Updated all callers to iterate directly instead of calling AddRange.
- Reorder GetItemSpecModifier parameters to put itemSpec first (the subject), modifier/modifierKind second (the operation), and context parameters (currentDirectory, definingProjectEscaped) last.
MSBuild should clear the new "defining project cache" held by ItemSpecModifiers when a build ends to avoid unbounded growth in long-lived MSBuild processes.
@SimaTian
Copy link
Copy Markdown
Member

Neat!

@SimaTian SimaTian merged commit 168763b into main Mar 24, 2026
10 checks passed
@SimaTian SimaTian deleted the dev/dustinca/itemspecmodifiers-perf branch March 24, 2026 13:05
JanProvaznik added a commit that referenced this pull request Mar 31, 2026
…and BuiltInMetadata performance (#13386)"

This reverts commit 168763b.
@JanProvaznik
Copy link
Copy Markdown
Member

Hi @DustinCampbell
MSBuild got a bug filed for Speedometer allocation regression.
By trying out reverting suspicious changes it pointed to this PR as the culprit:
bug: https://devdiv.visualstudio.com/DevDiv/_workitems/edit/2860443
revert: https://devdiv.visualstudio.com/DevDiv/_git/VS/pullrequest/723611
Could you please take a look?

@DustinCampbell
Copy link
Copy Markdown
Member Author

Hi @DustinCampbell MSBuild got a bug filed for Speedometer allocation regression. By trying out reverting suspicious changes it pointed to this PR as the culprit: bug: https://devdiv.visualstudio.com/DevDiv/_workitems/edit/2860443 revert: https://devdiv.visualstudio.com/DevDiv/_git/VS/pullrequest/723611 Could you please take a look?

Absolutely! Taking a look at the traces.

@DustinCampbell
Copy link
Copy Markdown
Member Author

After diffing the "GC Heap Alloc Ignore Free (Coarse Sampling Stacks)" between the base line and worst runs, it looks like the problem is TaskItem, and it seems to be exasperated cross AppDomain . I expect that's because of the new Cache struct type that's I added as a field to TaskItem.

Here's the increase in "TaskItem":

image

And here arethe callers of "TaskItem":

image

@DustinCampbell
Copy link
Copy Markdown
Member Author

Working on a fix via #13493.

dfederm pushed a commit to dfederm/msbuild that referenced this pull request Apr 9, 2026
…tInMetadata performance (dotnet#13386)

I recommend reviewing this pull request commit-by-commit.

# Summary of Changes

- Introduce new MSBuild.Benchmarks project for tackling performance
investigations.
- Add a few benchmarks for various methods on `ItemSpecModifiers`.
- Make several performance fixes related to `ItemSpecModifiers` and
`BuildInMetadata`.
- General clean up.

Across the board, most benchmarks are **3×–35× faster** with
**allocations eliminated or reduced by 93–100%**. The largest wins are
in repeated-access and multi-item scenarios, which are the most
representative of real build workloads. The full details are below but
here are the highlights.

## Highlights

### 🚀 Speed Improvements (.NET 10.0)

| Benchmark | Before | After | Speedup |
|---|---|---|---|
| `IsItemSpecModifier_AllModifiers` | 151.4 ns | 38.5 ns | **3.9×** |
| `GetItemSpecModifier_DefiningProjectDirectory` | 812.2 ns | 72.4 ns |
**11.2×** |
| `TaskItem_AllDerivableModifiers_Once` | 434.5 ns | 87.4 ns | **5.0×**
|
| `TaskItem_FilenameAndExtension_Repeated` | 908.5 ns | 173.7 ns |
**5.2×** |
| `TaskItem_Filename_ManyItems` | 9,651 ns | 1,857 ns | **5.2×** |
| `TaskItem_FullPathDerivedModifiers_Repeated` | 2,128 ns | 321.6 ns |
**6.6×** |
| `TaskItem_DefiningProjectDirectory_Repeated` | 9,121 ns | 970.8 ns |
**9.4×** |
| `PI_DefiningProjectDirectory_Repeated` | 9,092 ns | 1,021 ns |
**8.9×** |
| `PI_DefiningProjectFullPath_AllItems_Multi` | 35,245 ns | 9,947 ns |
**3.5×** |
| `PI_DefiningProjectDir_AllItems_Multi_Repeated` | 878,931 ns | 103,961
ns | **8.5×** |
| `PI_FilenameExtension_AllItems` | 22,698 ns | 5,343 ns | **4.2×** |
| `PI_FilenameExtension_AllItems_Repeated` | 181,612 ns | 67,028 ns |
**2.7×** |

### 🧹 Allocation Reductions (.NET 10.0)

| Benchmark | Before | After | Reduction |
|---|---|---|---|
| `TaskItem_AllDerivableModifiers_Once` | 1,232 B | **0 B** | 100% |
| `TaskItem_FilenameAndExtension_Repeated` | 640 B | **0 B** | 100% |
| `TaskItem_Filename_ManyItems` | 7,920 B | **0 B** | 100% |
| `TaskItem_FullPathDerivedModifiers_Repeated` | 7,120 B | **0 B** |
100% |
| `TaskItem_DefiningProjectDirectory_Repeated` | 8,240 B | **0 B** |
100% |
| `TaskItem_AllDefiningProjectModifiers_Once` | 912 B | **0 B** | 100% |
| `TaskItem_DefiningProjectNameExtension_AllItems` | 8,800 B | **0 B** |
100% |
| `GetItemSpecModifier_DefiningProjectDirectory` | 536 B | **0 B** |
100% |
| `PI_FilenameExtension_AllItems_Repeated` | 143,840 B | **640 B** |
99.6% |
| `PI_DefiningProjectDir_AllItems_Multi_Repeated` | 824,640 B | **640
B** | 99.9% |
| `PI_FilenameExtension_AllItems` | 14,384 B | **64 B** | 99.6% |
| `PI_DefiningProjectDirectory_Repeated` | 8,304 B | **64 B** | 99.2% |
| `PI_AllDerivableModifiers_Once` | 1,296 B | **64 B** | 95.1% |
| `PI_AllDefiningProjectModifiers_Once` | 976 B | **64 B** | 93.4% |

### 📊 .NET Framework 4.8.1

| Benchmark | Before | After | Speedup |
|---|---|---|---|
| `GetItemSpecModifier_DefiningProjectDirectory` | 5,467 ns | 156.8 ns |
**34.9×** |
| `TaskItem_DefiningProjectDirectory_Repeated` | 58,025 ns | 2,539 ns |
**22.9×** |
| `PI_DefiningProjectDir_AllItems_Multi_Repeated` | 6,399 μs | 282.3 μs
| **22.7×** |
| `TaskItem_Filename_ManyItems` | 110,078 ns | 6,916 ns | **15.9×** |
| `TaskItem_FullPathDerivedModifiers_Repeated` | 26,619 ns | 2,262 ns |
**11.8×** |
| `PI_FilenameExtension_AllItems_Repeated` | 2,162 μs | 202.6 μs |
**10.7×** |
| `TaskItem_AllDerivableModifiers_Once` | 5,322 ns | 507.2 ns |
**10.5×** |
| `PI_FilenameExtension_AllItems` | 216,406 ns | 20,366 ns | **10.6×** |
| `TaskItem_FilenameAndExtension_Repeated` | 10,238 ns | 664.7 ns |
**15.4×** |
| `PI_AllDerivableModifiers_Once` | 5,525 ns | 688.6 ns | **8.0×** |
| `PI_DefiningProjectDirectory_Repeated` | 64,204 ns | 2,796 ns |
**23.0×** |
| `PI_AllDefiningProjectModifiers_Once` | 9,808 ns | 1,154 ns | **8.5×**
|
| `TaskItem_AllDefiningProjectModifiers_Once` | 8,636 ns | 965.3 ns |
**8.9×** |

## 'Quick-and-Dirty' Telemetry

I had Copilot write some "quick-and-dirty" telemetry to track
information in `ItemSpecModifiers` and dump it to a file. I built
MSBuild with that extra telemetry and then built Roslyn (starting from
`Microsoft.VisualStudio.LanguageServices.CSharp.csproj`) using that
MSBuild. This gave me a dump with loads of interesting details. For
example, `IsItemSpecModifier` was called 901,057 times.

<details>
  <summary><b>Full Quick-and-Dirty Telemetry Dump</b></summary>

```
=== ItemSpecModifiers Telemetry (2026-03-12T09:38:41.0365991-07:00) ===

--- Top-level method calls ---
  IsItemSpecModifier:            901,057
  IsDerivableItemSpecModifier:   144,857
  GetItemSpecModifier:           180,890

--- Compute helper calls ---
  ComputeFullPath:     75,443
  ComputeRootDir:      84
  ComputeFilename:     57,426
  ComputeExtension:    32,071
  ComputeRelativeDir:  22
  ComputeDirectory:    84
  ComputeModifiedTime: 0
  ComputeCreatedTime:  0
  ComputeAccessedTime: 0

--- Per-modifier breakdown (inside GetItemSpecModifier) ---
  FullPath:                    44,783
  RootDir:                     41
  Filename:                    57,426
  Extension:                   6,462
  RelativeDir:                 22
  Directory:                   41
  RecursiveDir:                0
  Identity:                    15,814
  ModifiedTime:                0
  CreatedTime:                 0
  AccessedTime:                0
  DefiningProjectFullPath:     30,535
  DefiningProjectDirectory:    43
  DefiningProjectName:         0
  DefiningProjectExtension:    25,609

==========================================================
  Per-ItemSpec Modifier Hit Matrix
==========================================================

  Unique item specs seen:       13,809
  Item specs hit > 1 time:      13,005
  Grand total modifier lookups: 180,890

--- Top 50 hottest item specs (by total modifier calls) ---

  #1 (1,502 calls): System.Runtime.CompilerServices.InternalsVisibleTo
      Identity                              751
      DefiningProjectFullPath               751

  #2 (380 calls): D:\Projects\roslyn\artifacts\bin\Microsoft.CodeAnalysis\Debug\netstandard2.0\Microsoft.CodeAnalysis.dll
      FullPath                               17
      Filename                              280
      Extension                              40
      Identity                               21
      DefiningProjectFullPath                22

  #3 (270 calls): D:\Projects\roslyn\artifacts\bin\Microsoft.CodeAnalysis.Scripting\Debug\netstandard2.0\Microsoft.CodeAnalysis.Scripting.dll
      FullPath                               12
      Filename                              195
      Extension                              30
      Identity                               16
      DefiningProjectFullPath                17

  #4 (270 calls): D:\Projects\roslyn\artifacts\bin\Microsoft.CodeAnalysis.Workspaces\Debug\netstandard2.0\Microsoft.CodeAnalysis.Workspaces.dll
      FullPath                               12
      Filename                              195
      Extension                              30
      Identity                               16
      DefiningProjectFullPath                17

  #5 (247 calls): D:\.nuget\packages\system.threading.tasks.extensions\4.6.3\lib\netstandard2.0\System.Threading.Tasks.Extensions.dll
      FullPath                               13
      Filename                              221
      Identity                               13

  #6 (247 calls): D:\.nuget\packages\system.memory\4.6.3\lib\netstandard2.0\System.Memory.dll
      FullPath                               13
      Filename                              221
      Identity                               13

  #7 (247 calls): D:\.nuget\packages\system.buffers\4.6.1\lib\netstandard2.0\System.Buffers.dll
      FullPath                               13
      Filename                              221
      Identity                               13

  #8 (247 calls): D:\.nuget\packages\system.numerics.vectors\4.6.1\lib\netstandard2.0\System.Numerics.Vectors.dll
      FullPath                               13
      Filename                              221
      Identity                               13

  #9 (247 calls): D:\.nuget\packages\system.text.encoding.codepages\8.0.0\lib\netstandard2.0\System.Text.Encoding.CodePages.dll
      FullPath                               13
      Filename                              221
      Identity                               13

  #10 (247 calls): D:\.nuget\packages\system.runtime.compilerservices.unsafe\6.1.2\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll
      FullPath                               13
      Filename                              221
      Identity                               13

  #11 (245 calls): D:\.nuget\packages\microsoft.dotnet.arcade.sdk\10.0.0-beta.26160.1\tools\Assets\DotNetPackageIcon.png
      FullPath                               48
      Filename                               40
      Extension                              70
      Identity                                2
      DefiningProjectFullPath                37
      DefiningProjectDirectory                8
      DefiningProjectExtension               40

  #12 (245 calls): D:\Projects\roslyn\eng\targets\..\..\src\NuGet\ThirdPartyNotices.rtf
      FullPath                               48
      Filename                               40
      Extension                              70
      Identity                                2
      DefiningProjectFullPath                37
      DefiningProjectDirectory                8
      DefiningProjectExtension               40

  #13 (240 calls): D:\.nuget\packages\system.collections.immutable\10.0.1\lib\netstandard2.0\System.Collections.Immutable.dll
      FullPath                               12
      Filename                              216
      Identity                               12

  #14 (240 calls): D:\.nuget\packages\system.reflection.metadata\10.0.1\lib\netstandard2.0\System.Reflection.Metadata.dll
      FullPath                               12
      Filename                              216
      Identity                               12

  #15 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Web.dll
      FullPath                               13
      Filename                              208
      Identity                               13

  dotnet#16 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Threading.ThreadPool.dll
      FullPath                               13
      Filename                              208
      Identity                               13

  dotnet#17 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.IO.FileSystem.Watcher.dll
      FullPath                               13
      Filename                              208
      Identity                               13

  dotnet#18 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Resources.ResourceManager.dll
      FullPath                               13
      Filename                              208
      Identity                               13

  dotnet#19 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.IO.dll
      FullPath                               13
      Filename                              208
      Identity                               13

  dotnet#20 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.IO.Pipes.dll
      FullPath                               13
      Filename                              208
      Identity                               13

  dotnet#21 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.IO.MemoryMappedFiles.dll
      FullPath                               13
      Filename                              208
      Identity                               13

  dotnet#22 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.ValueTuple.dll
      FullPath                               13
      Filename                              208
      Identity                               13

  dotnet#23 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Console.dll
      FullPath                               13
      Filename                              208
      Identity                               13

  dotnet#24 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Linq.Parallel.dll
      FullPath                               13
      Filename                              208
      Identity                               13

  dotnet#25 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Security.Claims.dll
      FullPath                               13
      Filename                              208
      Identity                               13

  dotnet#26 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.IO.UnmanagedMemoryStream.dll
      FullPath                               13
      Filename                              208
      Identity                               13

  dotnet#27 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Threading.Overlapped.dll
      FullPath                               13
      Filename                              208
      Identity                               13

  dotnet#28 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Drawing.Primitives.dll
      FullPath                               13
      Filename                              208
      Identity                               13

  dotnet#29 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Net.WebSockets.dll
      FullPath                               13
      Filename                              208
      Identity                               13

  dotnet#30 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Security.Cryptography.Algorithms.dll
      FullPath                               13
      Filename                              208
      Identity                               13

  dotnet#31 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.IO.FileSystem.DriveInfo.dll
      FullPath                               13
      Filename                              208
      Identity                               13

  dotnet#32 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Diagnostics.Tracing.dll
      FullPath                               13
      Filename                              208
      Identity                               13

  dotnet#33 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Linq.Expressions.dll
      FullPath                               13
      Filename                              208
      Identity                               13

  dotnet#34 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Security.Principal.dll
      FullPath                               13
      Filename                              208
      Identity                               13

  dotnet#35 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Globalization.Calendars.dll
      FullPath                               13
      Filename                              208
      Identity                               13

  dotnet#36 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Security.Cryptography.Primitives.dll
      FullPath                               13
      Filename                              208
      Identity                               13

  dotnet#37 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.ObjectModel.dll
      FullPath                               13
      Filename                              208
      Identity                               13

  dotnet#38 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Xml.XDocument.dll
      FullPath                               13
      Filename                              208
      Identity                               13

  dotnet#39 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Collections.dll
      FullPath                               13
      Filename                              208
      Identity                               13

  dotnet#40 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.ComponentModel.TypeConverter.dll
      FullPath                               13
      Filename                              208
      Identity                               13

  dotnet#41 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Runtime.InteropServices.dll
      FullPath                               13
      Filename                              208
      Identity                               13

  dotnet#42 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Collections.Concurrent.dll
      FullPath                               13
      Filename                              208
      Identity                               13

  dotnet#43 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Collections.Specialized.dll
      FullPath                               13
      Filename                              208
      Identity                               13

  dotnet#44 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Dynamic.Runtime.dll
      FullPath                               13
      Filename                              208
      Identity                               13

  dotnet#45 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Net.Requests.dll
      FullPath                               13
      Filename                              208
      Identity                               13

  dotnet#46 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Security.Cryptography.X509Certificates.dll
      FullPath                               13
      Filename                              208
      Identity                               13

  dotnet#47 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Net.dll
      FullPath                               13
      Filename                              208
      Identity                               13

  dotnet#48 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.IO.Compression.ZipFile.dll
      FullPath                               13
      Filename                              208
      Identity                               13

  dotnet#49 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Xml.XmlSerializer.dll
      FullPath                               13
      Filename                              208
      Identity                               13

  dotnet#50 (234 calls): D:\.nuget\packages\netstandard.library\2.0.3\build\netstandard2.0\ref\System.Runtime.CompilerServices.VisualC.dll
      FullPath                               13
      Filename                              208
      Identity                               13

--- Repetition histogram (total modifier calls per item spec → count of item specs) ---

     1,502 calls  →         1 item specs
       380 calls  →         1 item specs
       270 calls  →         2 item specs
       247 calls  →         6 item specs
       245 calls  →         2 item specs
       240 calls  →         2 item specs
       234 calls  →       112 item specs
       226 calls  →         1 item specs
       224 calls  →         2 item specs
       204 calls  →         4 item specs
       196 calls  →         1 item specs
       164 calls  →        13 item specs
       160 calls  →         2 item specs
       151 calls  →         3 item specs
       144 calls  →        53 item specs
       140 calls  →         6 item specs
       138 calls  →         4 item specs
       134 calls  →         1 item specs
       132 calls  →         7 item specs
       122 calls  →         2 item specs
       117 calls  →        14 item specs
       113 calls  →       124 item specs
       111 calls  →         1 item specs
       110 calls  →         2 item specs
       109 calls  →         1 item specs
       101 calls  →         3 item specs
       100 calls  →         2 item specs
        99 calls  →         1 item specs
        98 calls  →         1 item specs
        91 calls  →         5 item specs
        89 calls  →        59 item specs
        86 calls  →         2 item specs
        84 calls  →         1 item specs
        82 calls  →         2 item specs
        80 calls  →         7 item specs
        78 calls  →         1 item specs
        76 calls  →         2 item specs
        75 calls  →         1 item specs
        74 calls  →         5 item specs
        73 calls  →         3 item specs
        72 calls  →         2 item specs
        70 calls  →         1 item specs
        66 calls  →         5 item specs
        65 calls  →         5 item specs
        60 calls  →        10 item specs
        58 calls  →         8 item specs
        57 calls  →         1 item specs
        56 calls  →         1 item specs
        54 calls  →         6 item specs
        52 calls  →         3 item specs
        51 calls  →         8 item specs
        50 calls  →         1 item specs
        49 calls  →         2 item specs
        48 calls  →         3 item specs
        47 calls  →         1 item specs
        46 calls  →         1 item specs
        45 calls  →        13 item specs
        44 calls  →        20 item specs
        41 calls  →         2 item specs
        40 calls  →         8 item specs
        39 calls  →         1 item specs
        37 calls  →         4 item specs
        36 calls  →        51 item specs
        35 calls  →         5 item specs
        34 calls  →         1 item specs
        33 calls  →         1 item specs
        32 calls  →         2 item specs
        30 calls  →         4 item specs
        29 calls  →        11 item specs
        28 calls  →        20 item specs
        27 calls  →        11 item specs
        26 calls  →        16 item specs
        24 calls  →        30 item specs
        23 calls  →         3 item specs
        22 calls  →       153 item specs
        21 calls  →         1 item specs
        20 calls  →        26 item specs
        19 calls  →         1 item specs
        18 calls  →       109 item specs
        16 calls  →        30 item specs
        15 calls  →        35 item specs
        14 calls  →       383 item specs
        13 calls  →       166 item specs
        12 calls  →     1,051 item specs
        11 calls  →         1 item specs
        10 calls  →        70 item specs
         9 calls  →        43 item specs
         8 calls  →     7,012 item specs
         7 calls  →        50 item specs
         6 calls  →       910 item specs
         5 calls  →     1,420 item specs
         4 calls  →       449 item specs
         3 calls  →        32 item specs
         2 calls  →       340 item specs
         1 calls  →       804 item specs
```
</details>

## Initial Benchmark Results

### .NET 10.0

| Method | Mean | Error | StdDev | Gen0 | Allocated |
|---------------------------------------------
|--------------:|------------:|------------:|-------:|----------:|
| IsItemSpecModifier_AllModifiers | 151.425 ns | 0.1309 ns | 0.1161 ns |
- | - |
| IsDerivableItemSpecModifier_RecursiveDir | 2.522 ns | 0.0028 ns |
0.0025 ns | - | - |
| GetItemSpecModifier_FullPath | 267.552 ns | 0.3441 ns | 0.3050 ns | -
| - |
| GetItemSpecModifier_Directory | 359.023 ns | 0.7603 ns | 0.6740 ns |
0.0224 | 376 B |
| GetItemSpecModifier_ModifiedTime | 28,544.061 ns | 237.0185 ns |
221.7073 ns | - | 176 B |
| GetItemSpecModifier_DefiningProjectDirectory | 812.229 ns | 3.3636 ns
| 2.9817 ns | 0.0315 | 536 B |
| TaskItem_AllDerivableModifiers_Once | 434.5 ns | 4.36 ns | 4.08 ns |
0.0734 | 1232 B |
| TaskItem_FilenameAndExtension_Repeated | 908.5 ns | 1.13 ns | 1.00 ns
| 0.0381 | 640 B |
| TaskItem_Filename_ManyItems | 9,651.3 ns | 29.02 ns | 25.72 ns |
0.4730 | 7920 B |
| TaskItem_FullPathDerivedModifiers_Repeated | 2,127.6 ns | 7.45 ns |
6.60 ns | 0.4234 | 7120 B |
| ProjectItemInstance_AllDerivableModifiers_Once | 513.4 ns | 2.93 ns |
2.74 ns | 0.0772 | 1296 B |
| ProjectItemInstance_FilenameExtension_AllItems | 22,697.6 ns | 68.62
ns | 64.19 ns | 0.8545 | 14384 B |
| ProjectItemInstance_FilenameExtension_AllItems_Repeated | 181,612.2 ns
| 1,125.69 ns | 940.00 ns | 8.5449 | 143840 B |
| ProjectItemInstance_AllDefiningProjectModifiers_Once | 1.559 μs |
0.0047 μs | 0.0040 μs | 0.0572 | 976 B |
| ProjectItemInstance_DefiningProjectDirectory_Repeated | 9.092 μs |
0.0654 μs | 0.0580 μs | 0.4883 | 8304 B |
|
ProjectItemInstance_DefiningProjectNameExtension_AllItems_SingleProject
| 12.515 μs | 0.0297 μs | 0.0263 μs | 0.5188 | 8864 B |
| ProjectItemInstance_DefiningProjectFullPath_AllItems_MultiProject |
35.245 μs | 0.0405 μs | 0.0379 μs | - | 64 B |
|
ProjectItemInstance_DefiningProjectDirectory_AllItems_MultiProject_Repeated
| 878.931 μs | 3.1495 μs | 2.7919 μs | 48.8281 | 824640 B |
| TaskItem_AllDefiningProjectModifiers_Once | 1.430 μs | 0.0027 μs |
0.0023 μs | 0.0534 | 912 B |
| TaskItem_DefiningProjectNameExtension_AllItems | 11.628 μs | 0.0289 μs
| 0.0241 μs | 0.5188 | 8800 B |
| TaskItem_DefiningProjectDirectory_Repeated | 9.121 μs | 0.0192 μs |
0.0170 μs | 0.4883 | 8240 B |

### .NET Framework 4.8.1

| Method | Mean | Error | StdDev | Gen0 | Allocated |
|---------------------------------------------
|-------------:|-----------:|----------:|-------:|----------:|
| IsItemSpecModifier_AllModifiers | 227.45 ns | 0.297 ns | 0.264 ns | -
| - |
| IsDerivableItemSpecModifier_RecursiveDir | 10.49 ns | 0.019 ns | 0.018
ns | - | - |
| GetItemSpecModifier_FullPath | 1,267.45 ns | 0.844 ns | 0.705 ns | - |
- |
| GetItemSpecModifier_Directory | 2,433.43 ns | 7.400 ns | 6.560 ns |
0.0954 | 517 B |
| GetItemSpecModifier_ModifiedTime | 41,881.06 ns | 111.954 ns | 93.487
ns | 0.1221 | 878 B |
| GetItemSpecModifier_DefiningProjectDirectory | 5,467.24 ns | 8.295 ns
| 6.926 ns | 0.1602 | 857 B |
| TaskItem_AllDerivableModifiers_Once | 5.322 μs | 0.0354 μs | 0.0331 μs
| 0.3662 | 1923 B |
| TaskItem_FilenameAndExtension_Repeated | 10.238 μs | 0.0108 μs |
0.0101 μs | 0.1373 | 761 B |
| TaskItem_Filename_ManyItems | 110.078 μs | 0.1367 μs | 0.1212 μs |
2.3193 | 12379 B |
| TaskItem_FullPathDerivedModifiers_Repeated | 26.619 μs | 0.1695 μs |
0.1585 μs | 2.1973 | 11578 B |
| ProjectItemInstance_AllDerivableModifiers_Once | 5.525 μs | 0.0311 μs
| 0.0276 μs | 0.3662 | 1959 B |
| ProjectItemInstance_FilenameExtension_AllItems | 216.406 μs | 0.2767
μs | 0.2160 μs | 2.9297 | 16422 B |
| ProjectItemInstance_FilenameExtension_AllItems_Repeated | 2,161.623 μs
| 10.4073 μs | 9.2258 μs | 31.2500 | 164225 B |
| ProjectItemInstance_AllDefiningProjectModifiers_Once | 9.808 μs |
0.0177 μs | 0.0165 μs | 0.2594 | 1418 B |
| ProjectItemInstance_DefiningProjectDirectory_Repeated | 64.204 μs |
0.3983 μs | 0.3726 μs | 2.3193 | 12616 B |
|
ProjectItemInstance_DefiningProjectNameExtension_AllItems_SingleProject
| 131.504 μs | 0.3383 μs | 0.3165 μs | 2.1973 | 12456 B |
| ProjectItemInstance_DefiningProjectFullPath_AllItems_MultiProject |
173.171 μs | 0.7242 μs | 0.5654 μs | - | 38 B |
|
ProjectItemInstance_DefiningProjectDirectory_AllItems_MultiProject_Repeated
| 6,399.063 μs | 71.6927 μs | 67.0614 μs | 234.3750 | 1242225 B |
| TaskItem_AllDefiningProjectModifiers_Once | 8.636 μs | 0.0177 μs |
0.0147 μs | 0.2594 | 1382 B |
| TaskItem_DefiningProjectNameExtension_AllItems | 126.982 μs | 0.2250
μs | 0.2104 μs | 2.1973 | 12420 B |
| TaskItem_DefiningProjectDirectory_Repeated | 58.025 μs | 0.1388 μs |
0.1299 μs | 2.3804 | 12579 B |

## Final Benchmark Results

### .NET 10.0

| Method | Mean | Error | StdDev | Gen0 | Allocated |
|---------------------------------------------
|--------------:|------------:|------------:|-------:|----------:|
| IsItemSpecModifier_AllModifiers | 38.4923 ns | 0.5501 ns | 0.5145 ns |
- | - |
| IsDerivableItemSpecModifier_RecursiveDir | 0.0000 ns | 0.0000 ns |
0.0000 ns | - | - |
| GetItemSpecModifier_FullPath | 260.1019 ns | 0.3623 ns | 0.3212 ns | -
| - |
| GetItemSpecModifier_Directory | 413.2121 ns | 1.9441 ns | 1.8185 ns |
0.0224 | 376 B |
| GetItemSpecModifier_ModifiedTime | 30,272.3116 ns | 408.0450 ns |
381.6855 ns | - | 176 B |
| GetItemSpecModifier_DefiningProjectDirectory | 72.3691 ns | 0.0289 ns
| 0.0270 ns | - | - |
| TaskItem_AllDerivableModifiers_Once | 87.41 ns | 0.226 ns | 0.200 ns |
- | - |
| TaskItem_FilenameAndExtension_Repeated | 173.68 ns | 1.812 ns | 1.695
ns | - | - |
| TaskItem_Filename_ManyItems | 1,856.79 ns | 1.128 ns | 0.942 ns | - |
- |
| TaskItem_FullPathDerivedModifiers_Repeated | 321.57 ns | 0.301 ns |
0.267 ns | - | - |
| ProjectItemInstance_AllDerivableModifiers_Once | 143.78 ns | 0.493 ns
| 0.462 ns | 0.0038 | 64 B |
| ProjectItemInstance_FilenameExtension_AllItems | 5,343.30 ns | 4.955
ns | 4.138 ns | - | 64 B |
| ProjectItemInstance_FilenameExtension_AllItems_Repeated | 67,028.30 ns
| 252.985 ns | 224.264 ns | - | 640 B |
| ProjectItemInstance_AllDefiningProjectModifiers_Once | 459.4 ns | 0.34
ns | 0.31 ns | 0.0038 | 64 B |
| ProjectItemInstance_DefiningProjectDirectory_Repeated | 1,020.5 ns |
0.56 ns | 0.47 ns | 0.0038 | 64 B |
|
ProjectItemInstance_DefiningProjectNameExtension_AllItems_SingleProject
| 20,091.0 ns | 17.96 ns | 16.80 ns | - | 64 B |
| ProjectItemInstance_DefiningProjectFullPath_AllItems_MultiProject |
9,946.7 ns | 5.28 ns | 4.68 ns | - | 64 B |
|
ProjectItemInstance_DefiningProjectDirectory_AllItems_MultiProject_Repeated
| 103,960.5 ns | 57.74 ns | 48.21 ns | - | 640 B |
| TaskItem_AllDefiningProjectModifiers_Once | 400.5 ns | 0.15 ns | 0.12
ns | - | - |
| TaskItem_DefiningProjectNameExtension_AllItems | 19,150.3 ns | 11.55
ns | 10.24 ns | - | - |
| TaskItem_DefiningProjectDirectory_Repeated | 970.8 ns | 0.62 ns | 0.55
ns | - | - |

### .NET Framework 4.8.1

| Method | Mean | Error | StdDev | Gen0 | Allocated |
|---------------------------------------------
|-------------:|-----------:|----------:|-------:|----------:|
| IsItemSpecModifier_AllModifiers | 106.532 ns | 0.4289 ns | 0.4012 ns |
- | - |
| IsDerivableItemSpecModifier_RecursiveDir | 5.067 ns | 0.0031 ns |
0.0024 ns | - | - |
| GetItemSpecModifier_FullPath | 1,331.138 ns | 1.4666 ns | 1.3001 ns |
- | - |
| GetItemSpecModifier_Directory | 2,471.887 ns | 4.2333 ns | 3.7527 ns |
0.0954 | 517 B |
| GetItemSpecModifier_ModifiedTime | 44,773.794 ns | 405.2647 ns |
359.2566 ns | 0.1221 | 878 B |
| GetItemSpecModifier_DefiningProjectDirectory | 156.840 ns | 0.2242 ns
| 0.1987 ns | - | - |
| TaskItem_AllDerivableModifiers_Once | 507.2 ns | 1.19 ns | 1.11 ns | -
| - |
| TaskItem_FilenameAndExtension_Repeated | 664.7 ns | 0.39 ns | 0.35 ns
| - | - |
| TaskItem_Filename_ManyItems | 6,916.2 ns | 4.03 ns | 3.77 ns | - | - |
| TaskItem_FullPathDerivedModifiers_Repeated | 2,261.6 ns | 3.34 ns |
2.96 ns | - | - |
| ProjectItemInstance_AllDerivableModifiers_Once | 688.6 ns | 1.01 ns |
0.94 ns | 0.0067 | 36 B |
| ProjectItemInstance_FilenameExtension_AllItems | 20,366.3 ns | 11.28
ns | 10.56 ns | - | 36 B |
| ProjectItemInstance_FilenameExtension_AllItems_Repeated | 202,570.4 ns
| 271.12 ns | 240.34 ns | - | 362 B |
| ProjectItemInstance_AllDefiningProjectModifiers_Once | 1,153.5 ns |
13.83 ns | 12.26 ns | 0.0057 | 36 B |
| ProjectItemInstance_DefiningProjectDirectory_Repeated | 2,795.7 ns |
17.33 ns | 16.21 ns | 0.0038 | 36 B |
|
ProjectItemInstance_DefiningProjectNameExtension_AllItems_SingleProject
| 46,236.9 ns | 105.16 ns | 93.22 ns | - | 36 B |
| ProjectItemInstance_DefiningProjectFullPath_AllItems_MultiProject |
28,362.1 ns | 34.50 ns | 30.58 ns | - | 36 B |
|
ProjectItemInstance_DefiningProjectDirectory_AllItems_MultiProject_Repeated
| 282,316.9 ns | 1,944.00 ns | 1,818.42 ns | - | 364 B |
| TaskItem_AllDefiningProjectModifiers_Once | 965.3 ns | 5.43 ns | 4.53
ns | - | - |
| TaskItem_DefiningProjectNameExtension_AllItems | 42,707.8 ns | 179.84
ns | 168.23 ns | - | - |
| TaskItem_DefiningProjectDirectory_Repeated | 2,539.1 ns | 9.64 ns |
8.05 ns | - | - |
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants