'Is there a way to align objects in C# same way as in C++ to avoid false sharing?

I am a C++ habitat working on a C# project.
I have encountered the following situation.

I have class MyClass and want to avoid any 2 objects of type MyClass ever to share a cache line even if I have an array or any sequential collection of type MyClass.
In C++ we can declare class alignas(hardware_destructive_interference_size) Myclass and this will make sure that any 2 objects never share a cache line.

Is there any equivalent method in C#?



Solution 1:[1]

No, you can't control the alignment or memory location of classes (reference types). You can't even get the size of a class instance in memory.

It is possible to control the size and alignment of structs (and of the fields within them). Structs are value types and work pretty much the same as in C++. If you create an array of a struct, each entry has the size of the struct, and if that is large enough, you could get what you want. But there's no guarantee that the individual entries are really distributed over cache lines. That will also depend on the size and organisation of the cache.

Note also that the address of a managed instance (whether a class or a struct) can change at runtime. The garbage collector is allowed to move instances around to compact the heap, and it will do this quite often. So there is also no guarantee that the same instance will always end up in the same cache line. It is possible to "pin" an instance while a certain block executes, but this is mostly intended when interfacing with native functions and not in a context of performance optimization.

Solution 2:[2]

From reading this page, it looks to me like you can use the following - for structs only though, not classes (my example would be for Intel CPUs):

[StructLayout(LayoutKind.Sequential, Pack=64)]

I can't see a guarantee anywhere that an object defined in this way will actually be allocated on (or indeed remain on) a 64 byte boundary, but this construct would not be of much use if it wasn't. If you want to check (and I personally most certainly would), there are some suggestions about how to get the address of an allocated object (until it moves!) here:

Memory address of an object in C#

I also can't see any way of not hard-coding the cache line size, but if you're always going to be running your code on Intel CPUs then that shouldn't be a problem, and I think (most) ARM chips also use 64 bytes, although not, apparently, Apple's M1 (huh!, typical).

Of course, if you do this you need to align the corresponding C++ class / struct accordingly. I think it would be wise to hard-code the alignment as 64 bytes there too, don't you? :)

Solution 3:[3]

aligned_alloc rounding the size up to the nearest cacheline.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 PMF
Solution 2
Solution 3 marc_s