What is the overhead of the fixed statement when u

2019-07-28 11:19发布

In particular, I'm thinking of a scenario like this:

    unsafe struct Foo
    {
        public int Bar;

        public Foo* GetMyAddr()
        {
            fixed (Foo* addr = &this)
                return addr;
        }
    }

Assuming a Foo stored in unmanaged memory, I'm trying to figure out what is involved in evaluating the fixed statement in GetMyAddr. I know as the programmer that this struct is never on the managed heap, I just need to get it's address in unmanaged memory in the most efficient manner. I'm especially concerned if there's any locking or atomic operations used here as that would make it completely unsuitable.

标签: c# unsafe
4条回答
家丑人穷心不美
2楼-- · 2019-07-28 11:29

The expression &this has no meaning when the structure is present in unmanaged memory. There is no way to allocate it there. A key property of managed structures is that their memory layout is not discoverable and is not compatible with the unmanaged view of that structure. The CLR rearranges fields as it sees fit to get the minimum size while aligning members. It will in fact swap fields if a later one can fit in the padding.

You cannot get past Marshal.PtrToStructure to convert an unmanaged struct to its managed version. Marshal.SizeOf is only accurate for the unmanaged layout.

查看更多
孤傲高冷的网名
3楼-- · 2019-07-28 11:35

Basically there's no overhead at all. Fixed means "pin the location the pointer points to in memory, don't relocate it." Every other managed pointer can be "bent" by the Garbage Collector at will if it decides to move memory around. Fixed will prevent this, so basically it will "save" this (possible) overhead.

I don't know about the implementation of fixed pointers, but in the simplest case it's just blacklisting memory blocks. This is not very costly compared to normal managed pointers.

On the other hand, it prevents all sorts of optimazations that the GC might decide to perform in terms of memory management like increasing localization, reducing fragmenation etc.

查看更多
时光不老,我们不散
4楼-- · 2019-07-28 11:46

This won't do what you think it will do. The "fixed" statement only pins the managed object (this) for the duration of the "fixed" statement itself, which ends as soon as you "return". See the MSDN docs for the details.

You already say your "Foo" is in unmanaged memory, which means that the managed GC isn't going to be moving it around on you. In that case, can't you just return "&this" directly? Alternatively, you may want to consider taking your unmanaged object and marshalling it into a managed one. Give a little more context around what you're doing and we'll all be able to give more specific advice.

查看更多
啃猪蹄的小仙女
5楼-- · 2019-07-28 11:54

I set up a micro benchmark and measured the overhead of fixed when used on a struct in unmanaged memory, it is very low, returning fixed(this) is only 10 times more expensive than simply returning this. That's acceptable for my use case (hashing using the address of the struct.) I was unable to learn how it was implemented, but it does seem to be fast enough in this case.

查看更多
登录 后发表回答