Data marshaling wrapper for a TCP server After a lot of research, I created this wrapper which I think fits very well to my needs. My project is a TCP server and I will be using this wrapper every time the server receives a packet. Basically, the wrapper will work marshaling raw byte[] into higher-level representation of the data as marshalable structs.

What do you think about this wrapper? Any hint on how I can improve it? I'm very concerned about performance.

public static class MyMarshal
{
    /// &lt;summary&gt;
    /// Marshals a raw buffer to a given marshalable struct.
    /// &lt;/summary&gt;
    public static unsafe T GetStructure&lt;T&gt;(byte[] buffer) where T : struct
    {
        fixed (byte* bufferPin = buffer)
        {
            return (T)Marshal.PtrToStructure(new IntPtr(bufferPin), typeof(T));
        }
    }

    /// &lt;summary&gt;
    /// Marshals a given T instance into a raw buffer.
    /// &lt;/summary&gt;
    public static unsafe byte[] GetBytes&lt;T&gt;(T obj) where T : struct
    {
        byte[] rawBuffer = new byte[Marshal.SizeOf(obj)];

        fixed (byte* rawBufferPin = rawBuffer)
        {
            Marshal.StructureToPtr&lt;T&gt;(obj, new IntPtr(rawBufferPin), false);
        }

        return rawBuffer;
    }

    /// &lt;summary&gt;
    /// Crates a zero-initialized marshaled instance of T
    /// &lt;/summary&gt;
    public static unsafe T CreateEmpty&lt;T&gt;() where T : struct
    {
        int typeSize = Marshal.SizeOf(typeof(T));

        byte* rawBuffer = stackalloc byte[typeSize];

        for (int i = 0; i &lt; typeSize; i++)
            rawBuffer[i] = 0;

        T zeroInited = (T)Marshal.PtrToStructure(new IntPtr(rawBuffer), typeof(T));

        return zeroInited;
    }
}


Summing up, the wrapper have 3 methods:


GetStructure (used right after I receive any valid packet to get the respective structure)
GetBytes (used when I want to send a packet to a client, converts a given struct value to a raw buffer to be send to the client)
CreateEmpty (used to create a zero-initialized instance of a given struct. This method is used when I have complex structures with non-blittable arrays, etc. The goal of this method is to have a generic zero-initializer method even to non-blittable structs - those with non-blittable arrays and/or strings).


I want to raise another questions too:


What do you think about this mixed use of unsafe code and the Marshal class? Is there any problem on using that way?
In the method MyMarshal.CreateEmpty, what do you think about the stackalloc usage? Some structures that will be initialized with this method will be a little big (usually something between 100 and 1024 bytes). Is there any downside or danger of allocating this length in the stack several times per seconds? I'm expecting to process something around 5k packet per second.


Also, he TCP server will work asynchronously using the async/await pattern, so I don't expect to deal with shared stated and other common problems to a multi-threaded application.
The wrapper seems pretty good to me.  The only change you might consider is that CreateWrapper really only needs to run once for each type; since these are structs it can return copies of the same empty object each time.  Something like this should work:

static class EmptyHolder&lt;T&gt; where T : struct
{
    public static T EmptyInstance;
    // assign EmptyInstance in static constructor
}


and then:

public static unsafe T CreateEmpty&lt;T&gt;() where T : struct
{
    return EmptyHolder&lt;T&gt;.EmptyInstance;
}


Of course there's a tradeoff of an uncollectable memory for each type you call this with.  And with anything performance-related, you'll need to measure to see if it delivers any benefit.  The original code should be pretty fast so maybe it's not significant.

There shouldn't be any danger in no matter how often you call stackalloc, by definition it's not possible for any two such calls to affect the same stack at the same time.  And there's no danger of any sort of recursion that would have more than 1 of these allocations on the same stack since the block is freed at the end of this function.