Unsafe C# trick to improve speed

后端 未结 3 2100
花落未央
花落未央 2021-02-19 14:02

I am not used to code with pointers (e.g. C++), nor with unsafe islands: only \"safe\" C#. Now I\'d like to implement a function in C# for the .Net Micro Framework, where the co

相关标签:
3条回答
  • 2021-02-19 14:24

    Look at this example from a different posting, on some code I have used extensively. You have the correct idea, just need to set the FieldOffset() values, and then use the fixed() keyword when accessing the data.

    This method is quite reliable, but not really much faster. The reason I use it, is because when I have lots of fields I want a quick way of accessing them as an array.

    0 讨论(0)
  • 2021-02-19 14:31

    I don't think the code is safe. After _structPtr = (MyStruct*)ptr which is within the fixed scope, you then go on to put data into _structPtr on the assumption that _struct2 won't move. Whilst you are correct that it won't be GCed, that doesn't mean that the GC won't move it during memory compaction. The .NET Compact Framework still garbage collects, and I assume it compacts memory rather than leaving it fragmented.

    If, for instance, a transient (non static) object allocated on the heap prior to _struct2 is removed by the GC then the memory in use by that struct may be shifted into the free space used by that transient object. At that point _structPtr is pointing to unused memory.

    Would modifying Test3() to take a ref MyStruct data help?

    Also, checkout [StructLayout(LayoutKind.Explicit)] and [FieldOffset(...)] which will allow you to have a single struct with multiple ways of accessing the same data within it. In your case either as 4 bytes or 1 int or (possibly) 1 array of 4 bytes.

    0 讨论(0)
  • 2021-02-19 14:45

    I don't think your "trick" is a problem. Nobody cares how you index memory, or how many offsets you use to accomplish it. I do think you need to heed the advice of others and make sure that you are controlling layout of your struct with StructLayout.Sequential, or .Explicit. Watch the Size and Pack options also.

    The other issue, which has been mentioned, is that you need to do all of your work in the fixed block.

    fixed (byte* ptr = struct2.Buffer)
    {
        var structPtr = (MyStruct*)ptr;
        var structIndex = 0;
        do
        {
            Test5(structPtr);
        } while (++structIndex < ArraySize);
    }
    

    Personally, I think you've stumbled into some Micro-Optimization theatre and would be better served by using safe C# code. Based on the numbers that you have given, (224x10^-3 - 177x10^-3) yields 47ms, divided by 5000 iterations nets you 9.4us (9.4x10^-6) per iteration (assuming windows isn't doing something else at the time).

    0 讨论(0)
提交回复
热议问题