none
Fastest -- way to move a byte array to a structure and back. RRS feed

  • Question

  • I want to encode a structure to Base64 and decode it back to a structure. What is the FASTEST way of doing this in .NET 4? FYI the structure is byte packed. The examples from the net show something like this to pack it. I was wondering if .NET 4 has grown up enough to handle binary data any faster.  


    unsafe public byte[] ToRaw()
    {
    byte[] byteArray = new byte[EntityState.PDU_SIZE];
    IntPtr pointer = Marshal.AllocHGlobal(EntityState.PDU_SIZE);
    Marshal.StructureToPtr(this, pointer, false);
    Marshal.Copy(pointer, byteArray, 0, EntityState.PDU_SIZE);
    Marshal.FreeHGlobal(pointer);
    return byteArray;
    }

    unsafe public byte[] ToRaw2()
    {
    byte[] byteArray = new byte[EntityState.PDU_SIZE];
    fixed (byte* ptr = byteArray)
    {
    *((EntityState*)ptr) = this;
    }
    return byteArray;
    }


    bfxtech.com
    Tuesday, October 19, 2010 10:15 PM

Answers

  • As a short answer, I would focus on using ToRaw2.  Personally, I don't know if it worth figuring out how to not do the fixed and pointer operations.  You can, of course, perform bit shifts and other low level stuff to compute the bytes you need without using fixed and pointers at all, if you wanted to.  Additionally, figure out some way that you do not need to do the new byte[...] with every call.  This will probably mean that you need some way to keep a "pool" of these buffers on hand and grab one that you are no longer using.  Since EntityState.PDU_SIZE appears to be a a constant, this job is made a lot easier since the pool can be populated by a bunch of buffers all of the same size which are interchangeable.  If your applications has multiple threads, your pool may need to be thread-safe.  This synchronization might dwarf the gains of all the fine optimizations we have been discussing.  Thus the pooling may need to be per-thread, perhaps using thread local storage.  But that has overhead too.  As you can see, you'll need to proceed carefully and with a lot of measurements/data to back up everything you do.  Such is the micro-optimizers life.

     

     

    • Marked as answer by btasa Monday, October 25, 2010 8:48 PM
    Wednesday, October 20, 2010 10:37 PM

All replies

  • That is a lot of dynamic allocation and deallocation going on.  If you are worried so much about "FASTEST", I take it you plan on doing this millions of time.  So the allocation should probably be a concern.  You are going to need to explain your scenario (how this fits into your program, why you are calling it often), so that someone can suggest ways to reduce all of the new byte[], Alloc, Free activity you've got going on.

    Common wisdom nowadays states that you should profile your code, and only worry about this if you have demonstrated that it is an actual performance problem.  All too common developers pick the wrong area of code to finely tune.  We'll assume that you have already done this ground work.

     

    Tuesday, October 19, 2010 10:56 PM
  • BinaryCoder..

    I built a prototype XML text encoding the struct and pushing it into my async source location then XML decoding it. It was fat and slow.

    What is going on is on demand queries that are rebroadcast to many users. I am using a queue system to do this. The typical query generates about 65,000 records of approximately 70 bytes in length binary. The queue can handle binary but the async readers can only handle text because of firewall issues. The speed of XML encoding decoding takes a 20 second query and turns it into 2 minutes.

    So how to make it faster? The speed slow down is encoding decoding and amount. How many times I have to read from the queue and how many items I can read from a remote location is a function of size and how long it takes to wrap and unwrap these items. So I started looking at Base64 encoding the compact text structure.

    >> I take it you plan on doing this millions of time >> I plan on doing 65 to 100 thousand each time and getting back the data ASAP. I found the text encoding and decoding in C# to be abysmal. The XML reader is no sir speedy either. So I am trying to make this faster.

     


    bfxtech.com
    Wednesday, October 20, 2010 2:14 PM
  • As a short answer, I would focus on using ToRaw2.  Personally, I don't know if it worth figuring out how to not do the fixed and pointer operations.  You can, of course, perform bit shifts and other low level stuff to compute the bytes you need without using fixed and pointers at all, if you wanted to.  Additionally, figure out some way that you do not need to do the new byte[...] with every call.  This will probably mean that you need some way to keep a "pool" of these buffers on hand and grab one that you are no longer using.  Since EntityState.PDU_SIZE appears to be a a constant, this job is made a lot easier since the pool can be populated by a bunch of buffers all of the same size which are interchangeable.  If your applications has multiple threads, your pool may need to be thread-safe.  This synchronization might dwarf the gains of all the fine optimizations we have been discussing.  Thus the pooling may need to be per-thread, perhaps using thread local storage.  But that has overhead too.  As you can see, you'll need to proceed carefully and with a lot of measurements/data to back up everything you do.  Such is the micro-optimizers life.

     

     

    • Marked as answer by btasa Monday, October 25, 2010 8:48 PM
    Wednesday, October 20, 2010 10:37 PM
  • Hi btasa,

    Are those replies helpful for you? It will be beneficial to other community members reading the thread if you could mark useful replies as answers.


    Sincerely,
    Eric
    MSDN Subscriber Support in Forum
    If you have any feedback of our support, please contact msdnmg@microsoft.com.
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
    Friday, October 22, 2010 4:27 AM
  • Sorry I have not been back for a while. Was busy coding. While away I wrote a base64 encoder/decoder in assembly and had someone wrap it into a DLL so I could use it in C#. The generic Base64 encoder/decoder I found on the net was milliseconds per encode writing it in assembly made it about 2 micro seconds. In reducing the bulk and eliminating the waste of .NET conversion I went from 2 plus minutes before a return to just under 30 seconds.

    Thanks

     


    bfxtech.com
    Monday, October 25, 2010 9:10 PM