Skip to content

Commit 3941d2b

Browse files
Reduce ItemSpecModifiers.Cache size
Recently, ItemSpecModifiers.GetItemSpecModifier was changed to take a Cache struct rather than a single "string? fullPath" parameter. Unfortunately, this increases memory allocations to an unexpected degree -- especially in cross-AppDomain scenarios. This change reduces the size of the Cache struct to just a single FullPath field, which should remove the allocation regression.
1 parent b013a87 commit 3941d2b

File tree

1 file changed

+7
-32
lines changed

1 file changed

+7
-32
lines changed

src/Framework/ItemSpecModifiers.cs

Lines changed: 7 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Licensed to the .NET Foundation under one or more agreements.
1+
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

44
using System;
@@ -52,35 +52,10 @@ internal static class ItemSpecModifiers
5252
DefiningProjectExtension
5353
];
5454

55-
/// <summary>
56-
/// <para>
57-
/// Caches derivable item-spec modifier results for a single item spec.
58-
/// Stored on item instances (e.g., TaskItem, ProjectItemInstance.TaskItem)
59-
/// alongside the item spec, replacing the former <c>string _fullPath</c> field.
60-
/// </para>
61-
/// <para>
62-
/// Time-based modifiers (ModifiedTime, CreatedTime, AccessedTime) and RecursiveDir
63-
/// are intentionally excluded — time-based modifiers hit the file system and should
64-
/// not be cached, and RecursiveDir requires wildcard context that only the caller has.
65-
/// </para>
66-
/// <para>
67-
/// DefiningProject* modifiers are cached separately in a static shared cache
68-
/// (<see cref="s_definingProjectCache"/>) keyed by the defining project path,
69-
/// since many items share the same defining project.
70-
/// </para>
71-
/// </summary>
7255
internal struct Cache
7356
{
7457
public string? FullPath;
75-
public string? RootDir;
76-
public string? Filename;
77-
public string? Extension;
78-
public string? RelativeDir;
79-
public string? Directory;
80-
81-
/// <summary>
82-
/// Clears all cached values. Called when the item spec changes.
83-
/// </summary>
58+
8459
public void Clear()
8560
=> this = default;
8661
}
@@ -420,19 +395,19 @@ public static string GetItemSpecModifier(
420395
return cache.FullPath ??= ComputeFullPath(currentDirectory, itemSpec);
421396

422397
case ItemSpecModifierKind.RootDir:
423-
return cache.RootDir ??= ComputeRootDir(cache.FullPath ??= ComputeFullPath(currentDirectory, itemSpec));
398+
return ComputeRootDir(cache.FullPath ??= ComputeFullPath(currentDirectory, itemSpec));
424399

425400
case ItemSpecModifierKind.Filename:
426-
return cache.Filename ??= ComputeFilename(itemSpec);
401+
return ComputeFilename(itemSpec);
427402

428403
case ItemSpecModifierKind.Extension:
429-
return cache.Extension ??= ComputeExtension(itemSpec);
404+
return ComputeExtension(itemSpec);
430405

431406
case ItemSpecModifierKind.RelativeDir:
432-
return cache.RelativeDir ??= ComputeRelativeDir(itemSpec);
407+
return ComputeRelativeDir(itemSpec);
433408

434409
case ItemSpecModifierKind.Directory:
435-
return cache.Directory ??= ComputeDirectory(cache.FullPath ??= ComputeFullPath(currentDirectory, itemSpec));
410+
return ComputeDirectory(cache.FullPath ??= ComputeFullPath(currentDirectory, itemSpec));
436411

437412
case ItemSpecModifierKind.RecursiveDir:
438413
return string.Empty;

0 commit comments

Comments
 (0)