Skip to content

Binlog forward compatibility and deserialisation-less reading support#1

Closed
JanKrivanek wants to merge 214 commits intoproto/binlog-replayfrom
proto/binlog-events-offsets
Closed

Binlog forward compatibility and deserialisation-less reading support#1
JanKrivanek wants to merge 214 commits intoproto/binlog-replayfrom
proto/binlog-events-offsets

Conversation

@JanKrivanek
Copy link
Copy Markdown
Owner

@JanKrivanek JanKrivanek commented Sep 26, 2023

Fixes dotnet#9261

Context

dotnet#9261
This builds on top of dotnet#9219 PR - but creating it as separate PR for easier review and for separate discussion. HJowever in the end it'd be preferrable to deliver those together - to require a single binlog contract increment

Changes

  • Added size info between even types and their content (as if the size info would be prior even type - we'd need to add it to all other record types - strings, lists, embedded files)
  • Adjusted the reading so that it can gracefully handle unknown events or data
  • Added event source for raw events

Measurements

OrchardCore build with debug version of MSBuild via dotnet build </bl>. Mean value of 5 runs used.
MSBuild version names used in following tables:

  • 'PR' - changes brought by this change
  • 'main' - base of this PR (d074c12)
  • 'RC1' - MSBuild version (0125fc9) inserted into RC1 - this is only for bigger picture comparison as there are dozens major changes between the 'RC1' and 'main'

File Size (bytes)

Version Rebuild % change vs main
PR 73351078 0.68%
main 72856382 0%
RC1 70378022 -3.4%

The increase is up to ~2.7% in case files are not embedded into binlog (ProjectImports=None, not a default)

Build speed

Version Rebuild % change vs main
PR 00:01:45.23 -1.7%
main 00:01:47.11 0%
RC1 00:01:46.25 -0.8%

Redacting speed

Version Redacting with autodetection % change vs main Redacting without autodetection % change vs main
PR 00:00:12.8617068 -46.6% 00:00:10.0419768 -53.8%
main 00:00:24.1082164 0% 00:00:21.7366761 0%

Future improvements

This change helps grace handling of under-reading of data for deserialized events (the assumption is newer version added data); but over-reading still leads hard error. Over-reading can be handled more gracefully as well (by leveraging SubStreams and break reading once the deserialization code is beyond the expected size of the serialized event)

assarbad and others added 7 commits July 28, 2023 23:35
- Also moved it to the bottom, because it is now the largest section
by review cleanup

Co-authored-by: Forgind <12969783+Forgind@users.noreply.github.com>
dfederm and others added 9 commits September 29, 2023 15:21
…001.1

Microsoft.Net.Compilers.Toolset
 From Version 4.8.0-3.23474.3 -> To Version 4.8.0-3.23501.1
…6.8.0.122

NuGet.Build.Tasks
 From Version 6.8.0-rc.117 -> To Version 6.8.0-rc.122
… content items from reference project to match thebehavior in VS tooling.
Add `[Required]` to parameters.

- `XmlPeek` Task
  - Change `Query` parameter.
  - Remove redundant `Dispose` that was flagged by the analyzer.
  - Change XmlPeek.XmlInput class from `Internal` to `private sealed` and change access of some members
  - Minor cleanup changes
- `XmlPoke` Task
  - Change `Query` parameter.
  - Change `XmlInputPath` parameter.
  - Minor cleanup changes
- XmlPeek_Tests class
  - Add new `PeekWithNoParameters` test
- XmlPoke_Tests class
  - Remove `PokeMissingParams` test
    - The test was defined as a `[Fact]` and used a for loop to test 4 distinct cases
    - The test expected `ArgumentNullException` to be thrown
  - Add 4 new tests, one for each of the four cases:
    - `PokeWithNoParameters`
    - `PokeWithMissingRequiredQuery`
    - `PokeWithMissingRequiredXmlInputPath`
    - `PokeWithRequiredParameters` (completes the replacement of `PokeMissingParams` but might be a redundant test)

Fixes dotnet#9140.
…81-9d7e-61a32415f962

[main] Update dependencies from dotnet/roslyn nuget/nuget.client
On windows there can be problems with Tools that do not support Unicode
The insertion release definition extends this when we try to insert, and
the VS release will extend it indefinitely for public builds.

Fixes a build warning in our official builds

    ##[warning]DropRetentionDays not set. Defaulting to 10 years (3650
    days). Please reduce drop retention period to 30 days if possible.
yuehuang010 and others added 11 commits October 6, 2023 15:58
RoslynTools.MSBuild 17.7.2 caused two CG alerts when doing signing validation. dotnet/arcade#14055 and its linked PRs have more context.
Fixes policheck:Error

Changes Made

Skip the non en-us locale resource files.
Skip the file that contains the specified entity names in the deprecated folder
Change country to country/region based on https://policheck.microsoft.com/Pages/TermInfo.aspx?LCID=9&TermID=79570

Testing
Test with MSBuild pipeline build https://devdiv.visualstudio.com/DevDiv/_build/results?buildId=8509007&view=logs&j=7d9eef18-6720-5c1f-4d30-89d7b76728e9&t=c5a86041-9185-53e8-42a2-1cadc4486f0d&l=5251. There are no active results now.
* Mention unification in RAR found-conflicts message

Consider a message like

```
warning MSB3277: Found conflicts between different versions of "System.Runtime.InteropServices.RuntimeInformation" that could not be resolved.
    There was a conflict between "System.Runtime.InteropServices.RuntimeInformation, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" and "System.Runtime.InteropServices.RuntimeInformation, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a".
    "System.Runtime.InteropServices.RuntimeInformation, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" was chosen because it was primary and "System.Runtime.InteropServices.RuntimeInformation, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" was not.
    References which depend on "System.Runtime.InteropServices.RuntimeInformation, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" [C:\VisualStudio\VS17PrevPublic\Common7\IDE\PublicAssemblies\System.Runtime.InteropServices.RuntimeInformation.dll].
        C:\VisualStudio\VS17PrevPublic\Common7\IDE\PublicAssemblies\System.Runtime.InteropServices.RuntimeInformation.dll
            Project file item includes which caused reference "C:\VisualStudio\VS17PrevPublic\Common7\IDE\PublicAssemblies\System.Runtime.InteropServices.RuntimeInformation.dll".
                System.Runtime.InteropServices.RuntimeInformation
    References which depend on "System.Runtime.InteropServices.RuntimeInformation, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" [].
        C:\Users\user\.nuget\packages\azure.core\1.25.0\lib\net461\Azure.Core.dll
            Project file item includes which caused reference "C:\Users\user\.nuget\packages\azure.core\1.25.0\lib\net461\Azure.Core.dll".
                C:\Users\user\.nuget\packages\azure.core\1.25.0\lib\net461\Azure.Core.dll
                C:\Users\user\.nuget\packages\azure.identity\1.8.0\lib\netstandard2.0\Azure.Identity.dll
                C:\Users\user\.nuget\packages\azure.security.keyvault.secrets\4.4.0\lib\netstandard2.0\Azure.Security.KeyVault.Secrets.dll
                C:\Users\user\.nuget\packages\nuget.services.keyvault\2.111.0\lib\net472\NuGet.Services.KeyVault.dll
                C:\Users\user\.nuget\packages\nuget.services.configuration\2.111.0\lib\net472\NuGet.Services.Configuration.dll
```

What the message _means_ is that the first reference is the winner, and
what was chosen there will require unification for all the other
assemblies listed in the second part of the message. But what it says is
that the list of assemblies in the second part of the message depend on
the second version, which is not necessarily true--in fact, that's the
list of  references that _can be unified_ to that version.

This isn't a full fix for dotnet#4757 but hopefully makes the message a bit
less misleading.

* Update tests

* fixup! Update tests
* Correct success

This is not yet a problem but only because neither /preprocess nor /targets are supported for solution files.

The root of the problem is if someone chooses to specify both /preprocess and /targets. If /preprocess fails but /targets succeeds, it currently will erroneously display success. This fixes that.

As I said, that scenario doesn't currently exist but only because /targets cannot succeed unless /preprocess succeeded, but that is not guaranteed going forward. Notably, if /preprocess is extended to support solution files before /targets is, this will become an issue.

* Make isTargets not run if !success

---------

Co-authored-by: Forgind <Forgind@users.noreply.github.com>
Fixes dotnet#7330
(plus one subtask of dotnet#8329)

Changes Made
Based on Add ability to create temp mapped drive for integration tests dotnet#8366 fixes to enable other Drive enumeration integration tests with a dummy folder in windows
Remove one test data https://github.com/dotnet/msbuild/blob/fecef0fdffe59ba8b0251701a23be48bbd552726/src/Build.OM.UnitTests/Instance/ProjectItemInstance_Tests.cs#L1010-L1012C45 since there is no warning when inlude is not null and exclude with enumerating wildcards. The related logical code is
msbuild/src/Build/Utilities/EngineFileUtilities.cs

Line 339 in fecef0f

 private static void LogDriveEnumerationWarningWithTargetLoggingContext(TargetLoggingContext targetLoggingContext, IElementLocation includeLocation, IElementLocation excludeLocation, bool excludeFileSpecIsEmpty, bool disableExcludeDriveEnumerationWarning, string fileSpec) 
. There is no condition satisfied.
Associate unix Enumeration Tests long time run with issue Unix drive enumeration imports not expanded? dotnet#8373
Preliminary design proposal for the Packages Sourcing feature
Fixes dotnet#8762

Context
Catch the exceptions when extensionsPathPropValue is null or importExpandedWithDefaultPath is empty.
In NET Framework, Path.* function also throws exceptions if the path contains invalid characters

Changes Made
Catch the exception.

Testing
FallbackImportWithInvalidProjectValue

Notes
.NET (Core) stuff is implied by ManagedDesktop now, and we require only
"some .NET Framework SDK", so no need to specify explicitly as one will
be delivered by ManagedDesktop.

We do still target .NET Framework 3.5, though . . .
…004.4 (dotnet#9314)

Microsoft.Net.Compilers.Toolset
 From Version 4.8.0-3.23501.1 -> To Version 4.8.0-3.23504.4

Co-authored-by: dotnet-maestro[bot] <dotnet-maestro[bot]@users.noreply.github.com>
…ngTargetExceptions (dotnet#9253)

Fixes dotnet#9245

Context
The test was disabled to unblock PR CI.

Changes Made
Increased the relevant timeout.

Testing
The test is reliably passing now.

Notes
This turned out to be an issue with the sleep command we use on Windows. In some cases PowerShell can take a super long time to start. I have been able to reproduce locally by enabling Fusion logging. Thread times of the powershell process:

image

We spend almost 10 seconds just loading assemblies, so the timeout of 10 seconds for the entire build was not enough.

I don't have a full understanding of the mechanism that slows down PowerShell this much. At this point I'm happy we were able to confirm it's not a product issue, although I'm wondering if there is a better and more light-weight sleep command we could use on Windows instead (e.g. ping 127.0.0.1 -n <seconds>). Reviewers please opine.

EDIT: In my trace, file system operations block extensively with wdfilter.sys on the stack, so the likely explanation for the issue appearing all of a sudden is a Defender update.
rainersigwald and others added 28 commits December 11, 2023 10:27
Right justify target and duration in terminallogger
…net#9511)

Prebuilt detection no longer detects Microsoft.SourceBuild.Intermediates as prebuilts due to dotnet/arcade#13935.

Addresses dotnet/source-build#3010
The devdiv build machine images appear to have started setting the
environment variable `NUGET_PACKAGES`, which caused a mismatch between
the location where `drop.app` was restored (repo-local location) and
where it was used from (environment-variable defined machine location),
causing build failures.

Co-authored-by: AR-May <67507805+AR-May@users.noreply.github.com>
…n.CurrentVersion.targets (dotnet#9520)

dotnet#9387 introduced improved hashing for [`[MSBuild]::StableStringHash`](https://learn.microsoft.com/en-us/visualstudio/msbuild/property-functions?view=vs-2022#msbuild-stablestringhash), that however broke internal functionality relying on the hash to be stable between versions (despite documented otherwise).

### Changes Made
 * Reverted all the hashing changes
 * Kept the UTD marker change (fixing dotnet#9346)

### Note
Longer term fix: dotnet#9519
NuGet's Central Package Management (CPM) allows users to specify package versions in a central location.  However, sometimes you may need to override the centrally defined version for a particular package so you specify the `VersionOverride` attribute documented [here](https://learn.microsoft.com/nuget/consume-packages/Central-Package-Management#overriding-package-versions).

Fixes AB#1929252.
…o-main

[automated] Merge branch 'vs17.9' => 'main'
* Add to change wave 17.10
* VersionSwitch test changed from Theory to Fact to remove overlap with other test
…otnet#9517)

* Update dependencies from https://github.com/nuget/nuget.client build 6.9.0.50

NuGet.Build.Tasks
 From Version 6.9.0-preview.1.45 -> To Version 6.9.0-preview.1.50

* Update dependencies from https://github.com/dotnet/roslyn build 20231208.9

Microsoft.Net.Compilers.Toolset
 From Version 4.9.0-3.23602.1 -> To Version 4.9.0-3.23608.9

---------

Co-authored-by: dotnet-maestro[bot] <dotnet-maestro[bot]@users.noreply.github.com>
…o-main

[automated] Merge branch 'vs17.9' => 'main'
* Change Extended args api back to be compatible with 17.8

* Bump version

* Revert "Bump version"

---------

Co-authored-by: Jan Krivanek <jankrivanek@microsoft.com>
* Version 17.10 (dotnet#9499)

* Remove U2D marker dependency on ProjectGuid property

* Revert "Version 17.10"

---------

Co-authored-by: AR-May <67507805+AR-May@users.noreply.github.com>
Fixes dotnet#9513

Context
Creation of CODEOWNERS file as per request in issue. Having a code owners file would also be generally useful when opening PRs in this repo, as it can sometimes be difficult and time consuming to determine who should be included as a reviewer.

Changes Made
Added @dotnet/source-build-internal as code owners for SB files
Added @dotnet/kitten as code owner for some of files and folders.

Testing
No testing
…SBuild.exe only) (dotnet#9439)

Fixes dotnet#9303

### Context

After a new version of `VS.Redist.Common.Net.Core.SDK.MSBuildExtensions` is inserted into VS, a native image for `Microsoft.DotNet.MSBuildSdkResolver` will be generated, both for devenv.exe and MSBuild.exe (see dotnet/installer#17732).

We currently load SDK resolvers using `Assembly.LoadFrom` on .NET Framework, which disqualifies it from using native images even if they existed. This PR makes us use the native image.

### Changes Made

Added a code path to use `Assembly.Load` to load resolver assemblies. The call is made such that if the assembly cannot be found by simple name, it falls back to loading by path into the load-from context, just like today. The new code path is enabled only for `Microsoft.DotNet.MSBuildSdkResolver` under a change-wave check.

### Testing

Experimental insertions.

### Notes

Using `qualifyAssembly` in the app config has the advantage of keeping everything _field-configurable_, i.e. in the unlikely case that a custom build environment will ship with a different version of the resolver, it will be possible to compensate for that by tweaking the config file. The disadvantage is that the same `qualifyAssembly` will need to be added to devenv.exe.config because .pkgdef doesn't support this kind of entry, to my best knowledge. It should be a one-time change, though, because [we have frozen the version of `Microsoft.DotNet.MSBuildSdkResolver` to 8.0.100.0](dotnet/sdk#36733).
* Update dependencies from https://github.com/dotnet/arcade build 20231130.1

Microsoft.DotNet.Arcade.Sdk , Microsoft.DotNet.XUnitExtensions
 From Version 8.0.0-beta.23463.1 -> To Version 8.0.0-beta.23580.1

Dependency coherency updates

Microsoft.DotNet.XliffTasks
 From Version 1.0.0-beta.23426.1 -> To Version 1.0.0-beta.23475.1 (parent: Microsoft.DotNet.Arcade.Sdk

* Bump minimum MSBuild and xcopy version for post-build

---------

Co-authored-by: dotnet-maestro[bot] <dotnet-maestro[bot]@users.noreply.github.com>
Co-authored-by: Rainer Sigwald <raines@microsoft.com>
Fixes dotnet#5881

Context
Implementation of proposed ITaskItem[] SourceFolders parameter.

Changes Made
Within Copy.cs:

Added ITaskItem[] SourceFolders parameter
Modified ValidateInputs() to support the new parameter
Modified InitializeDestinationFiles()
Previously this method iterated SourceFiles to create DestinationFiles items given the DestinationFolder.
The Copy task actually only operates on SourceFiles and DestinationFiles.
Extended the method to:
Use FileMatcher::GetFiles() for each directory in SourceFolders
Create items in both SourceFiles and DestinationFiles for each file found
Added additional unit tests in Copy_Tests.cs.

Added new error MSB3894 Copy.IncompatibleParameters for the case where SourceFolders and DestinationFiles are both present. This is very close to the existing MSB3022 Copy.ExactlyOneTypeOfDestination but it seemed prudent not to re-use MSB3022.

Testing
Tested on Windows 11 and macOS 12

Ran full suite of unit tests from the command line

Ran some sample project files

Notes
This implementation conforms to the proposed design with the exception that it does not copy empty directories.

This implementation leverages the existing FileMatcher::GetFiles() which recurses the directory tree using multiple threads. GetFiles() returns a list of files. Empty directories are not identified.

The use of FileMatcher could be replaced. The Copy task could implement its own support for recursing a directory tree. The wildcard matching logic in FileMatcher is not relevant for the Copy task.
Context
We still have checks for a change wave that's already out of rotation.

Changes Made
[MSBuild]::AreFeaturesEnabled('17.0') is now unconditionally true, let's remove the checks from Microsoft.Common.CurrentVersion.targets.
…o-main

[automated] Merge branch 'vs17.9' => 'main'
Fixes dotnet#9131

Context
As described on the issue, muti-targeted builds did not import the .user file on the outer build. This change makes the outer build import the .user file.

Changes Made
Added import reference to .user file in  Microsoft.Common.CrossTargeting.targets .

Testing
Test is in SDK repo (dotnet/sdk#37192)
…tnet#9446)

Related to dotnet#9303

### Context

We load `NuGet.Frameworks` lazily by path when the project being evaluated calls one of a few property functions that need it. All standard .NET projects use such functionality so this load is executed pretty much always. Since we're loading the assembly by path, the loader is unable to take advantage of the native image and we spend 50-100 ms JITting.

### Changes Made

Improved MSBuild.exe startup (or, more precisely, first evaluation) by 50-100 ms by loading `NuGet.Frameworks` into a separate AppDomain using `Assembly.Load`. The AppDomain is set up with the right binding redirects for the loader to load the assembly by strong name and use its native image.

### Testing

Experimental insertions.

### Notes

There are several other assemblies that require non-trivial JITting on startup. The reason why we're tackling `NuGet.Frameworks` here are:
- The assembly has no dependencies other than Framework assemblies, so the AD setup is relatively simple.
- The functionality provided by this assembly has simple signatures so the cross-domain call cost is negligible.
- A compatible native image for this assembly already exists.

Other notes:
- There is no impact on VS or any other MSBuild host because creating ADs may be risky and disruptive. We're changing only MSBuild.exe.
- This PR is about the `NuGet.Frameworks` copy that lives in `{VS-installation}\Common7\IDE\CommonExtensions\Microsoft\NuGet`. The MSBuild process may also load SDK-specific copies from paths like `C:\Program Files\dotnet\sdk\8.0.100\Sdks\Microsoft.NET.Sdk\tools\net472` which are out of scope here.

This is what the AD looks like in SOS:

```
Domain 2:           000001dff97c7e70
Stage:              OPEN
Name:               NuGetFrameworkWrapper
Assembly:           000001dff6bac490 [C:\windows\Microsoft.Net\assembly\GAC_64\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll]
Assembly:           000001dff9732960 [C:\src\msbuild\artifacts\bin\bootstrap\net472\MSBuild\Current\Bin\Microsoft.Build.dll]
Assembly:           000001dff97e2410 [C:\src\msbuild\artifacts\bin\bootstrap\net472\Common7\IDE\CommonExtensions\Microsoft\NuGet\NuGet.Frameworks.dll]
Assembly:           000001dff8de7250 [C:\windows\Microsoft.Net\assembly\GAC_MSIL\System.Core\v4.0_4.0.0.0__b77a5c561934e089\System.Core.dll]
Assembly:           000001dff8dd6100 [C:\windows\Microsoft.Net\assembly\GAC_MSIL\System\v4.0_4.0.0.0__b77a5c561934e089\System.dll]
Assembly:           000001dff8e1d9a0 [C:\windows\Microsoft.Net\assembly\GAC_MSIL\System.Xml\v4.0_4.0.0.0__b77a5c561934e089\System.Xml.dll]
```
We were hard-coded to an ancient version of NuGet.exe, but we should be fine taking the latest stable, which is default for NuGetToolInstaller.
JanKrivanek pushed a commit that referenced this pull request Apr 8, 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

  dotnet#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

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

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

  dotnet#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

  dotnet#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

  dotnet#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

  dotnet#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

  dotnet#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

  dotnet#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

  dotnet#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

  dotnet#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.