-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Optimize CopyRefAssembly task by checking file size and timestamp before MVID extraction #80635
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Co-authored-by: baronfel <[email protected]>
Co-authored-by: baronfel <[email protected]>
| File.WriteAllText(dest.Path, "dest"); | ||
|
|
||
| // Ensure different timestamps to test MVID checking path | ||
| System.Threading.Thread.Sleep(10); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@copilot don't use thread sleeps in the tests, instead just compute a time delta for the equivalent change and use File.SetLastWriteTimeUtc directly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. Replaced all Thread.Sleep calls with direct timestamp manipulation using File.SetLastWriteTimeUtc. Now we compute a time delta (e.g., destTime.AddSeconds(1)) instead of sleeping. (commit: TBD)
| if (File.Exists(DestinationPath)) | ||
| { | ||
| // Fast path: check size and timestamp first to avoid expensive MVID extraction | ||
| try |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@copilot can you find existing performance benchmark tests and add a benchmark comparison for the cost of this check compared to the full mvid check? #Closed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added PerformanceComparison_SizeTimestampCheckVsMvidCheck test that demonstrates the fast path is significantly faster than MVID extraction. The test runs 100 iterations of each approach and validates that the MVID path takes more time than the size/timestamp check. In local testing, the MVID path is typically 10-20x slower. (commit: TBD)
Co-authored-by: baronfel <[email protected]>
Co-authored-by: baronfel <[email protected]>
|
@jaredpar FYI |
| } | ||
|
|
||
| [Fact] | ||
| public void PerformanceComparison_SizeTimestampCheckVsMvidCheck() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@copilot instead of this test, create a separate benchmarkdotnet test showing the difference in the two implementations. run the benchmarks and report back the difference.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Created a separate BenchmarkDotNet project at src/Tools/MSBuildTaskBenchmarks. Benchmark results show:
- Fast Path (Size/Timestamp Check): 4.141 μs
- Slow Path (MVID Extraction): 35.049 μs
- Combined Check: 4.091 μs
The optimization provides an 8.6x performance improvement when files haven't changed. The fast path also uses 95% less memory (472 B vs 8,960 B). (commit: TBD)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we should keep the benchmark code in the repo. Are we going to run it ever again?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we should keep the benchmark code in the repo. Are we going to run it ever again?
@jjonescz Asking you since you've approved the PR already, what do you think of removing the added benchmark code?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I agree, we don't need the code checked in.
Co-authored-by: baronfel <[email protected]>
Co-authored-by: baronfel <[email protected]>
jcouv
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done with review pass (commit 7)
Oh, interesting. Copilot PRs do not have the required I will investigate this within the next week, as it will apply to all repos using dotnet/issue-labeler. Thanks for letting me know; I logged Pull Request Labeling does not run automatically for Copilot PRs (dotnet/issue-labeler#105). |
|
From offline discussion it seems the benefits are not significant, so I'm unsure if we want to continue working on this PR, @baronfel? These are results @jaredpar measured (using the benchmark from this PR presumably): https://gist.github.com/jaredpar/6651f8555f11232ac3797ccfcac0049c |
|
I still want this, given that it happens on every single build of every single project, even those that are incredibly incremental. 100ms on framework and 30ms on core does add up over time. |
|
@baronfel Moving this PR to draft as our PR queue is pretty full. There's only minor feedback to address (removing benchmark tests). Feel free to undraft when ready. |
Summary
This PR optimizes the
CopyRefAssemblyMSBuild task to significantly improve performance on incremental builds by adding a fast-path check before expensive MVID extraction.Problem
As reported in the issue, the
CopyRefAssemblytask was taking considerable time even on incremental builds. The task runs for every TFM of every C# project, and was always extracting and comparing MVIDs from both source and destination assemblies, even when the files were identical.Solution
Following @jjonescz's suggestion, this PR implements a size and timestamp check before MVID extraction, similar to how MSBuild's standard
Copytask works:Benefits
Performance Validation
Created a dedicated BenchmarkDotNet project (
src/Tools/MSBuildTaskBenchmarks) to measure the performance improvement. Benchmark results demonstrate:Key Findings:
Testing
Added comprehensive test coverage:
SourceAndDestinationWithSameSizeAndTimestamp- Validates the new fast-path optimizationSourceAndDestinationWithSameMvidButDifferentTimestamp- Ensures MVID checking still works correctlyThread.Sleepfor deterministic and faster test executionAll 7 CopyRefAssembly tests pass (378 tests total in the MSBuildTaskTests suite).
Fixes #80611
Original prompt
Fixes #80611
✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.