Search code examples
c#.net-core

What memory model is implemented in .NET Core?


The ECMA CLI specification defines a weak memory model. This allows to reorder the command execution order (which is useful for performance). But writing low-level code for such a model is very difficult.

And most importantly - X86/AMD64 processor architectures have a more strict (strong) memory model. As a result, Microsoft implemented a stronger memory model in its CLR implementation than described in the specification.

Has the memory model changed in .NET Core? Potentially, this framework can run on architectures with a weaker memory model than X86/AMD64.

In addition, .NET Core incorporates Mono and other. And as far as I know, the Mono memory model is weaker, corresponds to ECMA.

In this article Introducing .NET 5 written:

Expand the capabilities of .NET by taking the best of .NET Core, .NET Framework, Xamarin and Mono.

So I think if not now, then in the future these runtimes will merge into a single whole.
Below in the article it is written:

We’re in the process of making CoreCLR and Mono drop-in replacements for one another. We will make it as simple as a build switch to choose between the different runtime options.

If I understand correctly, there will be two (or more) runtimes. And probably everyone will have their own memory model.

What are we talking about: Memory Model.


Solution

  • The memory model is specific to the runtime, so your question is in fact "are there any differences in the memory models of CLR, CoreCLR and MonoRuntime".

    After researching a bit, I found that the question is really, really difficult to answer. There is the ECMA specification that you have mentioned, which gives you the bare minimum guarantees that all implementations must provide. There's a very nice, concise description on Joe Duffy's blog for CLR 2.0. Then, for .NET Framework there is this two part article that speaks about the CLR model in probably more details than it's healthy to know about. There's even a paper written on that.

    For MonoRuntime, I've found this doc that talks about atomics and actually describes the way Mono implements this, though the level of detail is rather low.

    Finding details of CoreCLR is even trickier. There are some keypoints highlighted in this dotnet/coreclr GitHub thread and a discussion about volatile read/writes in this one.

    The simplest way to answer is - yes, it has changed, based on the above resources.

    However, there is a second way of answering your question and that is to simply deny its premise - it seems to assume that the memory model changed in the sense that some smart people sat down, rewrote the ECMA CLI spec, made that into the CoreCLR memory-model spec and that's the new memory-model. That is not the case. The mentioned smart people sat down and, over the course of many months, refined the design to be reliable, fast, sensibly easy to implement and not in violation of the minimum guarantees of the spec. Citing from the linked Joe Duffy's blog:

    We have constructed our model over years of informal work and design-by-example (...) this is apt to change from one implementation to the next.

    The informal ECMA specification is, unfortunatelly, as formal as we get for now. There is no formal description of changes between the ECMA spec and the CLR implementation, nor is there a formal description of changes between CLR and CoreCLR. And, more importantly, the implementation specific differences between the ECMA CLI and CLR/CoreCLR are just that - implementation specific - and must not be relied upon. The only 100% reliable source of how the .NET Core memory model is implemented is the source code. And that obviously changes with every commit, every release, and there is no guarantee that the team won't throw the entire jitter out the window and rewrite it for .NET 5 to be exact same as the ECMA spec (however wildly unlikely that is).