Chad,
Short of manipulating everything in bytes yourself, there is little you
can do that will improve the performance. Because you want to work with the
fields as strings, you will have to perform some marshaling back and forth
(because strings in .NET are composed of characters, which are two bytes
each).
If you go back to using the byte arrays in the structure (which you
could do using the ByValArray value on the UnmanagedType enumeration), it is
the equivalent of what marshalling is essentially doing for you.
BTW, your locking code is incorrect. You are locking on rawslot, which
is of type IntPtr. This is a structure, and when passed as a parameter of
type object, it is boxed, with a new object instance each time. This means
that you actually lock on the buffer the first time, and never let it go
(the call to Exit will box with a different object).
I can't see how this method runs on more than one thread, considering
you never give up the lock.
On the one hand, you can eliminate the lock, and allocate the buffer as
needed each time this is called. However, this might be a little
inefficient. You could also share a buffer among all the threads, but then
you would have to lock on it.
I think the best solution is to have a buffer which is allocated
per-thread (when the threads are created). You can do this easily by
declaring a field as static, and adding the ThreadStaticAttribute to the
field. The CLR will make sure that each thread has it's own instance.
With this in place, you can assign the buffer to each thread (when the
thread starts, so you don't have to check each time), and then not have to
lock.
If you don't do a per-thread approach, and need a lock, then use the
lock statement. If your method throws an exception, your lock will be
released properly.
Also, you should have a separate static field with an instance of object
stored in it. You can use this as your lock.
--
- Nicholas Paldino [.NET/C# MVP]
-
mvp@spam.guard.caspershouse.com
<taskswap@gmail.com> wrote in message
news:1136997461.652345.318050@g47g2000cwa.googlegr oups.com...[color=blue]
> OK, thanks. The ByValTStr has helped a lot. However, I still have a
> piece of unsafe code used to transfer each message into its appropriate
> structure. It looks like:
>
> fixed (void *p = &buffer[offset]) {
> IntPtr ip = new IntPtr(p);
> m = (MsgAddProduct) Marshal.PtrToStructure(ip,
> typeof(MsgAddProduct);
> }
>
> I have a byte[] buffer that contains my message, starting at offset. I
> use this code to transfer the bytes into the new structure, defined as
> you've listed above.
>
> This all works, but it still seems somewhat inefficient. What's the
> overhead involved in the work above? This is going to happen thousands
> of times a second, so I need it to be as efficient as possible. In C I
> used to just define a structure, cast the buffer pointer to a structure
> pointer, and access my fields. This works in unsafe mode in C#, but not
> with strings. I haven't found any better way of accessing string data
> than what you've defined above.
>
> Next inefficiency is on send side. I need to send from byte[] buffers
> but my message size is limited, so I may have to split a structure
> across multiple messages. Somehow I need to get a structure divided up
> into one or more byte[] buffers.
>
> I currently do this:
> public unsafe void SendObject(object x) {
> Monitor.Enter(rawslot);
> Marshal.StructureToPtr(x, rawslot, false);
> Send((byte *) rawslot, Marshal.SizeOf(x));
> Monitor.Exit(rawslot);
> }
>
> rawslot is a 16K block created with AllocHGlobal. But this seems
> inefficient - I marshal the struct to unmanaged memory, then copy it
> AGAIN into each message buffer? Now that the messages are managed
> structures, the compiler won't let me make a fixed byte* pointer or
> byte[] reference to them - it says they're already fixed. The above
> code is the only thing I've found that works.
>
> Is there a better way to do either of these? Can I possibly union a
> byte array into the structure somehow? That would make things much
> easier, but I haven't found the right syntax.
>
> Thanks,
> Chad
>[/color]