views:

211

answers:

2

I have a class that will have a few instances persistent throughout the duration of the application. These objects will each need to call a dll method that appends data from an existing float[] buffer, and passes the full dataset to a DLL method that accepts an IntPtr (float array), several times per second. Is it better to do it as unmanaged code:



    class PersistentThing : IDisposable {
        readonly IntPtr _floats = Marshal.AllocHGlobal(sizeof(float) * ArraySize);

        public void DoFrequentAction() {
            // Append data from a buffer to the memory space.
            var floatOffsetPtr = new IntPtr(_floats.ToInt32() + _floatsIndex * sizeof(float));
            Marshal.Copy(_buffer, _bufferIndex, floatOffsetPtr, _bufferCount);

            // Call a DLL method with with memory pointer
            CallDllMethod(_floats);
        }

        // Need to dispose the unmanaged memory
        public void Dispose() {
            Marshal.FreeHGlobal(_floats);
        }
    }

or would it be better to use an unsafe tag and fixed?


    class PersistentThing2 {
        readonly float[] _floats = new float[ArraySize];

        public unsafe void DoFrequentAction() {
            // Append data from a buffer to the memory space.
            Array.Copy(_buffer, _bufferIndex, _floats, _floatsIndex, _bufferCount);

            // Call a DLL method with with memory pointer
            fixed (float* floatsPtr = _floats) {
                CallDllMethod((IntPtr)floatsPtr);
            }
        }
    }

Is there any advantage of not having to use the "unsafe" tag in the compiler? Is the Marshal class actually any "safer"? Which of these methods generally have the better performance?

I lean toward the former, just because that way the GC doesn't have to worry about _floats (which could be quite large) when cleaning up the memory space. Is that a reasonable concern? Does the recommendation depend on the size of ArraySize?

+1  A: 

In both cases, you're calling native, unsafe code.

I prefer the second option - it's cleaner, easier to follow, and more obvious. It also doesn't force IDisposable on you for your array to be collected.

Reed Copsey
A: 

I ultimately learned that both solutions are fine. Performance is about the same and the GC won't have an impact on the 2nd solution, since the object would either be allocated to the Large Object Heap and never moved, or quickly be promoted to 2nd generation on the garbage collector and moved very rarely.

Dax