Skip to content

Share SDK resolution during Pack and Publish discovery - #55426

Merged
OvesN merged 7 commits into
dotnet:mainfrom
OvesN:dev/veronikao/shared-evaluation-context-pack-publish
Jul 29, 2026
Merged

Share SDK resolution during Pack and Publish discovery#55426
OvesN merged 7 commits into
dotnet:mainfrom
OvesN:dev/veronikao/shared-evaluation-context-pack-publish

Conversation

@OvesN

@OvesN OvesN commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Summary

ReleasePropertyProjectLocator already uses properties-only partial evaluation to discover PackRelease and PublishRelease. This change keeps ProjectEvaluationStage.Properties and reuses one short-lived EvaluationContext across all physical-project evaluations performed by a single discovery operation.

The selected policy is Shared. It provides the best measured process-start-to-first-MSBuild-submission duration for both Pack and Publish and shares SDK resolution, filesystem observations, and wildcard/import expansion state across the physical-project discovery evaluations.

The context is scoped to one short-lived release-property discovery operation, and the existing parallel solution evaluation remains fully parallel without an external lock.

Performance

Related changes measured together:

The measurement uses dotnet.cli.process_start_to_msbuild_submission.duration, recorded immediately before the first Pack/Publish MSBuild invocation.

  • OrchardCore OrchardCore.slnx
  • 12 measured iterations per variant across three independent runs
  • balanced rotated/reversed variant ordering
  • dotnet pack OrchardCore.slnx --no-build
  • dotnet publish OrchardCore.slnx --no-build
  • one process-local dotnet-cli histogram measurement per invocation

This metric covers CLI process startup, argument parsing, physical project/solution discovery, and the hidden ReleasePropertyProjectLocator evaluations. It excludes the subsequent MSBuild build execution.

The same SDK binaries selected three local-only variants:

Variant Evaluation stage Evaluation context
Full + Isolated Full Isolated
Properties + Isolated Properties Isolated
Properties + Shared Properties Shared

Pack results

Variant Mean Median Min–max Median improvement vs Full + Isolated Paired wins Median paired improvement
Full + Isolated 3,831.31 ms 3,799.61 ms 3,712.47–4,307.89 ms baseline
Properties + Isolated 2,921.96 ms 2,887.24 ms 2,836.86–3,135.66 ms 912.37 ms (24.01%) 12/12 881.80 ms
Properties + Shared 1,395.70 ms 1,363.86 ms 1,267.78–1,669.86 ms 2,435.75 ms (64.11%) 12/12 2,442.79 ms

For Pack, partial evaluation reduced the median by 912.37 ms (24.01%). Sharing the context then reduced the partial-evaluation median by another 1,523.38 ms (52.76%). Together they reduced pre-submission time by 2,435.75 ms (64.11%).

Publish results

Variant Mean Median Min–max Median improvement vs Full + Isolated Paired wins Median paired improvement
Full + Isolated 3,943.95 ms 3,986.13 ms 3,597.08–4,313.38 ms baseline
Properties + Isolated 3,170.96 ms 3,000.78 ms 2,720.49–5,448.23 ms 985.35 ms (24.72%) 11/12 986.79 ms
Properties + Shared 1,426.54 ms 1,434.54 ms 1,225.69–1,723.40 ms 2,551.59 ms (64.01%) 12/12 2,549.53 ms

For Publish, partial evaluation reduced the median by 985.35 ms (24.72%). Sharing the context then reduced the partial-evaluation median by another 1,566.24 ms (52.19%). Together they reduced pre-submission time by 2,551.59 ms (64.01%).

One Properties + Isolated Publish sample was an outlier at 5,448.23 ms, so medians are the primary summary. Properties + Shared still improved all 12 paired rounds relative to Full + Isolated.

End-to-end wall-clock results

Total command time was measured separately with successful --no-build --no-restore operations:

  • Pack: full OrchardCore OrchardCore.slnx
  • Publish: a successful 101-project OrchardCore modules/themes solution
  • MSBuild server and node reuse disabled
  • the same 12-sample balanced ordering

Later MSBuild work is unaffected by these evaluation optimizations and dominates total time. Machine throughput also changed substantially between Publish runs, so paired comparisons within each run/round are the primary wall-clock result.

Command Full + Isolated median Properties + Shared median Pooled median improvement Median paired improvement Paired wins
Pack 40,110.42 ms 37,442.84 ms 2,667.58 ms (6.65%) 2,509.67 ms (6.30%) 10/12
Publish 26,273.55 ms 25,114.17 ms 1,159.37 ms (4.41%) 2,468.60 ms (7.87%) 11/12

Paired median decomposition:

Command Partial evaluation Shared context incremental Combined
Pack 745.53 ms (1.88%) 2,001.90 ms (5.05%) 2,509.67 ms (6.30%)
Publish 685.96 ms (2.60%) 1,171.73 ms (4.17%) 2,468.60 ms (7.87%)

Correctness

  • The context is created after the existing disable/configuration early exits.
  • Its lifetime is limited to one release-property discovery operation.
  • It is passed through project, directory, .sln, .slnx, lazy-solution, and physical-project evaluation paths.
  • The existing parallel solution evaluation remains fully parallel.
  • Properties-only partial evaluation remains enabled.
  • Existing release-property tests pass under Isolated, SharedSDKCache, and Shared prototypes.
  • ProjectGraph already uses one full Shared evaluation context across parallel project evaluations.
  • The compatibility boundary is that filesystem state must remain stable for the lifetime of the discovery call. This operation immediately evaluates an already-discovered project or solution and does not intentionally mutate project/import files.

Virtual/file-based projects

Virtual/file-based project discovery remains unchanged and out of scope. It performs full evaluation because it reads items such as Compile, and sharing its context would require threading the context through all virtual and referenced-virtual-project evaluations with dedicated behavior coverage.

Tests

  • Added a locator test that performs two discovery calls in the same process, mutates import existence between calls, and verifies that the first call's shared filesystem observations are not retained by the second call.

Remaining risk

Full Shared caches file/directory existence, timestamps, and wildcard/import expansions. If evaluation-time behavior mutates those inputs while discovery is in progress, later evaluations using the same context can observe the cached pre-mutation state. The context is therefore intentionally created per discovery call and discarded before restore or the subsequent MSBuild invocation.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).
2 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

@baronfel baronfel added Area-CLI cli-ux Issues and PRs that deal with the UX of the CLI (exit codes, log output, verbs/options, and so on) Area-MSBuild labels Jul 23, 2026
OvesN and others added 2 commits July 27, 2026 10:11
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@OvesN
OvesN marked this pull request as ready for review July 29, 2026 07:05
@OvesN
OvesN requested review from a team as code owners July 29, 2026 07:05
Copilot AI review requested due to automatic review settings July 29, 2026 07:05
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).
2 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This pull request improves dotnet pack/dotnet publish “Release property” discovery performance by sharing MSBuild SDK resolution and related evaluation caches across the short-lived, properties-only project evaluations performed during discovery (especially for solutions).

Changes:

  • Reuse a single EvaluationContext (SharingPolicy Shared) across all ProjectInstance evaluations in a single ReleasePropertyProjectLocator discovery operation.
  • Extend solution conflict tests to exercise both .sln and migrated .slnx inputs.
  • Add new unit tests validating that shared evaluation context behavior remains correct (no cross-call retention; path-specific imports and conditional missing imports remain project-specific).

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.

File Description
src/Cli/dotnet/ReleasePropertyProjectLocator.cs Create and thread a shared EvaluationContext through all properties-only ProjectInstance evaluations during Pack/Publish Release property discovery.
test/Microsoft.NET.Publish.Tests/GivenThatWeWantToTestAMultitargetedSolutionWithPublishReleaseOrPackRelease.cs Extend the conflicting PackRelease/PublishRelease solution test to run against both .sln and .slnx (via dotnet sln migrate).
test/dotnet.Tests/CommandTests/Pack/ReleasePropertyProjectLocatorTests.cs Add focused unit tests to ensure shared-context caching doesn’t leak across discovery calls and remains project-path specific for imports/Exists conditions.

OvesN and others added 2 commits July 29, 2026 09:19
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Comment thread src/Cli/dotnet/ReleasePropertyProjectLocator.cs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area-CLI Area-MSBuild cli-ux Issues and PRs that deal with the UX of the CLI (exit codes, log output, verbs/options, and so on)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants