Skip to content

Proposed .NET 7 Breaking Changes #7131

Open
@richlander

Description

@richlander

The following list defines breaking changes that are proposed for .NET 7.

Implemented:

Planned for .NET 7:

Unclear plan:

Moved to .NET 8:

No longer honor multi-level-lookup (MLL) for .NET 7+ apps, runtimes and SDKs

Proposal: https://github.com/dotnet/designs/blob/main/accepted/2022/disable-multi-level-lookup-by-default.md
Change: dotnet/runtime#67022
Notice: dotnet/docs#28836

Multi-level-lookup (MLL) -- specified with DOTNET_MULTILEVEL_LOOKUP -- is relevant when an alternate location is specified to look for SDKs and/or runtimes, via DOTNET_ROOT. When enabled, MLL expands the search space for runtimes and SDKs to include the global .NET installation location in addition to the DOTNET_ROOT location. This can result in a runtime or SDK being selected from the global installation location rather than the intended private DOTNET_ROOT location, whether that is desired or not.

Motivation for break:

  • MLL results in lots of confusion, both for .NET developers and even for folks working on the .NET platform.
  • MLL behavior differs by OS: enabled by default on Windows, not available on any other OS.
  • No known scenario where this feature is required.

Stop adding 32-bit .NET to the PATH for .NET 7+ runtimes and SDKs (on x64 machine)

Proposal: dotnet/sdk#22030
Change: dotnet/runtime#69902
Notice: dotnet/runtime#70039

Note: This change was made to .NET Core 3.1, .NET 6, and .NET 7.

When you install .NET, the installer adds the install location to the PATH environment variable. This behavior is sound and enables the OS to find dotnet when you use it. We build multiple .NET for multiple architectures (x86, x64, ...). In some cases, an OS supports multiple architectures and then we need a plan for how multiple .NET locations in the PATH works. In short, it doesn't work well. Going forward, we should only ever add the OS native-architecture .NET install location to the PATH. We already started doing that on Apple M1 (Arm64) machines (we only add the Arm64 .NET to the PATH, not the x64 version). We need to repeat this pattern with Windows now, with the 32-bit .NET build.

Motivation for break:

  • Adding multiple builds of .NET to the PATH is incoherent, results in bad UX, and is difficult to explain.
  • We have already started down this direction with x64 on Arm64. It makes sense to make the product consistent, by repeating the pattern with x86 on x64 and x86 on Arm64.

dotnet build/publish uses the implicit SDK RID for RID-specific apps by default

Proposal: dotnet/sdk#23539
Change: dotnet/sdk#22314
Notice: not actually breaking

Today, you must specify a RID when you specify "--self-contained". That's not a useful requirement, particularly if you want to app to be able to run in a given environment (like CI) and don't know what that is ahead of time. Instead, the implicit SDK RID should be used in any scenario where a RID is needed but one isn't provided. The most obvious example of that is to produce a self-contained app.

FYI: This is arguably not a breaking change.

Motivation for break:

  • The CLI should have good defaults where correct behavior can be provided in absence of the user provided a specific value.
  • RID targeting is confusing. We should make it simpler.

dotnet publish/pack produce release assets by default

Proposal: dotnet/sdk#23551

Our basic guidance to developers since .NET Core 1.0 has been "use build for development and publish for prod". Given that, it would make a lot more sense if publish defaulted to a release build. Debug builds run observably slow (sometimes you can see this with just your eyes; no stopwatch required). It is near certain that plenty of .NET apps are deployed as debug due to the current defaults. The CLI would be much better if it offered more differentiated options. There should probably be a more broad re-assessment of build and publish but I'm not digging into that here. I'm proposing a much more simpler change (that doesn't preclude broader changes later; in fact, this change would encourage them).

Motivation for break:

  • release assets have better performance (sometimes by a large margin).
  • Some CLI commands bias strongly to prod, which provides us with a good opportunity to provide a differentiated prod experience. We don't want developers deploying debug assets into prod unwittingly. Differentiated experiences can help that.

dotnet build/publish produces RID-specific apps by default

Proposal: dotnet/sdk#23540

The .NET SDK has produced portable apps since .NET Core 1.0. That may or may not have made sense, but it no longer does now. Portable apps are bigger, slower to startup, and less reliable in some scenarios. In addition, portable apps are not fully coherent since they have a RID-specific executable but portable assets. That means that you can use the executable for one RID environment and cannot for any other. It's an odd design choice. A perfect example is containers. RID-specific apps are always better for containers. Another example is client apps. Client apps require an executable, such that they should always be RID-specific.

Motivation for break:

  • Portable apps are good for a small subset of scenarios.
  • RID-specific apps are the only good option for a variety of popular scenarios.

dotnet build/publish does not produce an exe/apphost for portable apps by default

Proposal: dotnet/sdk#23545

Portable apps are intended to run in multiple environments. By definition, an executable is RID-specific and therefore only compatible with one of the environments in which a portable app can run. It's possible that developers are happy with this asymmetry, but should opt into that experience.

Motivation for break:

  • The apphost makes portable apps incoherent.
  • It is easier to explain how to use portable apps in absence of an executable apphost.

Precompile with AVX2 (x64) or NEON (Arm64) instructions for better startup performance

Proposal: dotnet/designs#173

Vector (SIMD) instructions are now one of the key performance pillars of the .NET platform. Today, pre-compiled Ready-to-Run (R2R) code targets the SSE2 instruction set on x64. We require the JIT to tier the platform to tier 1 in order to take advantage of larger/newer vector instructions (like AVX2). That model penalizes startup on modern hardware and also places a hard dependency on tiered compilation for good performance. Ideally, R2R code was already very good, and tiered compilation was reserved for only the highest value methods. We can achieve that by compiling R2R code with AVX2 (x64) and NEON (Arm64) by default. We would not change the Windows 32-bit or Arm 32-bit builds.

Note: After this change, machines with AVX2 will have better performance, while machines w/o it will end up with worse performance since some R2R methods will be rejected and require jitting where they previously did not.

Motivation for break:

  • Highest performance, including at startup.
  • Align product to modern hardware.

For additional context, SSE2-compatible hardware was first released in 2000, and the same for AVX2 in 2013.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions