Skip to content
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

Add plan for x64 emulation #217

Merged
merged 3 commits into from
Aug 17, 2021
Merged

Add plan for x64 emulation #217

merged 3 commits into from
Aug 17, 2021

Conversation

richlander
Copy link
Member

We're working on a plan to support .NET for x64 emulation on Arm64, on macOS and Windows. There are multiple decision points that we are needing to navigate to make a decision. This document is intended to explore those.


### Rely on the implicit rid of the SDK

In theory, the easiest approach is to simply use the matching SDK for the rid you want to target. That's the model used in the "developing and targeting on Windows x64" example discussed earlier.
Copy link
Member

Choose a reason for hiding this comment

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

What is the "developing and targeting on Windows x64" example that this talks about?

Copy link
Member Author

@richlander richlander May 6, 2021

Choose a reason for hiding this comment

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

It just means that if you develop on Windows x64 and deploy to Windows x64 for prod, rid targeting isn't something you need to think about. Same thing with Linux x64 (for development and prod). You need to think more about rid targeting when the development environment and prod environment don't match in operating system and/or architecture dimensions. Make sense?

Copy link
Member

Choose a reason for hiding this comment

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

Yes, makes sense. I was commenting more on the fact that this example is not actually discussed earlier in this doc, and so people reading this doc for the first time will be lost.

Copy link
Member Author

Choose a reason for hiding this comment

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

Fixed.


Goal: Enable developers to produce architecture-specific assets correctly and with confidence.

The .NET application model is oriented around rid-specific apps. In particular, the apphost is rid-specific, and the apphost ia a core part of the experience. In some scenarios, you don't have to pay much attention to the rid of the apphost. For example, if you exclusively develop on *and* target Windows x64, then rid-targeting isn't really important, even though it is present. If your development and target environment differ, then you need to directly participate in rid-targeting.
Copy link

Choose a reason for hiding this comment

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

typo: apphost ia a core part

Copy link
Member Author

Choose a reason for hiding this comment

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

fixed.

There are problems with this model:

- Using the x64 SDK will be a substandard experience, primarily due to it not being in the `PATH`. On macOS, you can either type `/usr/local/share/dotnet/x64/dotnet`, prepend that directory to the `PATH`, create a shell alias, or create a symbolic link (in `/usr/local/bin`). Some of those same options exist on Windows.
- Users will find it confusing and unpleasant to need to pivot between the x64 and Arm64 SDKs as a means of targeting a .NET version (short-term problem) or RID (long-term problem).
Copy link

Choose a reason for hiding this comment

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

Does it mean osx-arm64 installer will also include osx-x64 .NET SDK?

Copy link
Member Author

Choose a reason for hiding this comment

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

Great q. No. I updated the text.

@yaakov-h
Copy link
Member

yaakov-h commented May 7, 2021

On the macOS front, do universal binaries ("fat binaries") factor in at all, or is .NET going to ignore its existence entirely?

@richlander
Copy link
Member Author

Great q @yaakov-h. Search for "universal binaries" @ dotnet/sdk#16896.

The short version is that they are not a silver bullet and add significant cost. We'd also have to invent a way for .NET 6 Arm64 and x64 to co-exist that would likely end up looking a lot like this plan. I think that universal binaries end up being mostly an implementation detail as opposed to a fundamentally different direction.

I should say that we discussed universal binaries only related to the dotnet host and its direct native dependencies (not the runtime). We firmly rejected compiling the entire product as universal. That has massive cost for us and significant UX implications. We could imagine compiling the runtime that way, but our ready-to-run native code would have to participate, too. The product would become huge. There is no chance we go down that path.

@yaakov-h
Copy link
Member

yaakov-h commented May 21, 2021

Another question related to that, which I haven't seen mentioned anywhere yet:

On macOS and similar platforms (iOS, potentially tvOS?) with multi-architecture binaries, a .NET app may have a dependency on a native library which has multiple architecture slices.

Can/will .NET deal with these binaries as-is, or does/will .NET require the binary to be either duplicated across or split into architecture-specific directories in NuGet packages etc.?

@richlander
Copy link
Member Author

That's a good question. As long as OS library loader is used to load the native binary, then the correct slice should be selected. I believe that's what will happen by default.

Make sense?

@yaakov-h
Copy link
Member

I believe so too, but is there a common folder for each OS where .NET runtimes/SDKs will search regardless of architecture?

@richlander
Copy link
Member Author

Are you asking if there is a universal binary concept (for a given OS) for NuGet packages so that you can single instance a binary?

@yaakov-h
Copy link
Member

For NuGet, but also for published applications.

Can I have / will I be able to have, for example, a universal binary at runtimes/osx/native/libfoo.dylib, or do I need both runtimes/osx-x64/native/libfoo.dylib and runtimes/osx-arm64/native/libfoo.dylib?

@richlander
Copy link
Member Author

Right. That is what I was getting at. The answer is that you need both copies, even though they'd be identical. If we start to get significant requests for this, we can add support for this scenario. I don't think it is very hard since it's just another (less specific) entry in the RID graph. Feel free to file an issue for a universal RID for macOS in dotnet/runtime. Same thing would apply for Windows. This is also a change that we could take in servicing, post RTM.

@rhuijben
Copy link

What about the Windows ARM64EC platform support?

This is x64 compatible ARM64 on latest Windows platforms, but with an ABI that looks more like x64 than ARM64.

I can see scenarios where you want native .Net support on this architecture for performance reasons.

@richlander
Copy link
Member Author

We didn't adopt ARM64EC because it's non obvious which architecture dotnet.exe should choose.

@ddavidebor
Copy link

@richlander to clarify, is there any way to use X64 dlls from a .net app compiled to Arm64 ?

Because that's the use case for Arm64EC, but is seems that currently if an app uses .net, it's not possible to take advantage of Arm64EC and the app has to be 100% recompiled, including any SDKs that might be supplied as DLLs by 3rd parties.

@jkotas
Copy link
Member

jkotas commented Dec 18, 2023

@ddavidebor You can run your x64 app with full emulation. The app is still going to take advantage of Arm64EC for the Windows OS .dlls that are all compiled with Arm64EC option. Our experience is that the x64 emulator has good enough performance.

Arm64EC is just a performance optimization of the x64 emulation. Arm64EC is always going to be slower than native Arm64 when everything else is equal. Our focus has been on the native Arm64 performance.

@ddavidebor
Copy link

ddavidebor commented Dec 20, 2023

If I understand this correctly, this is the only way transition a large app written in C# with both C# and C++ dependencies without having to port everything all at once:

  1. Run it in fully x64 emulated mode.
  2. Recompile some of those SDKs/DLLs C/C++ to ARM64EC
  3. Run it in x64 emulated mode, but it will take advantage of the newly recompiled DLLs
  4. Finish porting everything to Arm64
  5. Run it in Arm64 mode

is that correct?

@jkotas
Copy link
Member

jkotas commented Dec 20, 2023

Correct. This whole process is a performance optimization, and it is not specific to .NET. If the performance is good enough in step 1, you do not have to do the rest.

@jozefizso
Copy link

Our experience is that the x64 emulator has good enough performance.

We see extremely bad performance in MS Office add-ins built using .NET and targeting x64 platform.

@richlander
Copy link
Member Author

I assume that's running x64 Office. Yes?

@rwg0
Copy link

rwg0 commented Jan 7, 2024

I would potentially have a use case for an ARM64EC version of the runtime. I have a relatively large .NET WPF app that includes a considerable amount of my own C++ code for performance and also needs to make use of DLLs provided by 3rd parties.

I can (and have) rebuilt my C++ code as ARM64, but getting ARM64 versions of the 3rd party DLLs is hard. Often these DLLs control hardware and the drivers are actually easier to find than the control DLLs (winusb, hid devices need no special drivers, etc). Being able to run the .NET runtime and my C++ code in ARM64 gives much better performance than full x64 emulation. Being able to emulate x64 for DLLs that are either unavailable or unported to ARM64 lets the ARM version progress incrementally.

From my point of view, an additional platform target of 'ARM64EC' target for build and publish would be sufficient - I publish self contained, so wouldn't worry if the installed runtime didn't support ARM64EC.

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.

8 participants