0
Answer

How to minimize Marshalling overhead in calling unmanaged codes?

macausimonho

macausimonho

20y
2.7k
1
I found the overhead of Marshal unmanged code is very heavy when string is involved; I tried many things to minimize it but it' seemed not much helpful. Are there any ways to get aournd the Marshalling? I also found a fact that string type with CharSet = CharSet.Unicode could run very fast but I double this trick might be blocked in future; please see (3) below for detail. What I did: (1) [SuppressUnmanagedCodeSecurity()] does help speed up the I/O (appx. 2 times faster) when the parameters are in "Blittable" data types (byte, interger, etc). However, when the parameters invlove with non-blittable data types such as string or StrinBuilder, then the help becomes immaterial. e.g. a) UnmangeCall( no param) saves 1,000ms in 10 million calls. b) UnmangeCall( StringBuilder) takes extrac 20,000 ms; so [SuppressUnmanagedCodeSecurity()] has little help only. 2) Still employ Blittable type such as byte: use byte pointer allocated memory from stackalloc(); this makes the UnmanageCall( byte *) with Blittable data type. That's help a lot (a factor of 10 times) but byte array ULTIMATELY needs to Marshal back to manage types e.g.: ... byte * blittableString = stackalloc byte[length]; ... Marshal.Copy(sourceStringToCharArray(), 0, new IntPtr( blittableString ), lenght / 2); UnmanageCall( byte * blittableString ); string result = Marshal.PtrToStringUni(new IntPtr(blittableString ), lenght ); The cost of the Marshalling effect is heavy and it ultimately balances out the gain from the UnmanageCall( bittableString ). 3) I found some interest thing in CLR: if string type is used with CharSet =CharSet.Unicode, the overhead just the same the blittable data type, very fast (I think there is actually no Marshalling in between). Although string is immutable and CLR does not allow string to be modifed by copied back from unmanaged code) but I found that in case of CharSet.Unicode (if .ANSI, then it is no allowed), CLR does use the same buffer (instead of copying to another buffer and that is why it is much faster) to pass the stream, the unmanged code made changes to the buffer and the managed code does see the changes. So this (un-blittable type) may get around the Mashalling cost. Of course I shouldn't rely on this trick as string type is not pinned and the buffer is not garanteed but it seems there is no way to minimize the cost, especially to use C# as a tool to implement server side codings. To summarize, Mashalling and UnicodeEncoding post heavy overhead in unmanaged environment. I hope .NET will make enhancement on these so that serious developer can consider using .NET to develop server side applications. Does anyone has another suggestion? Should I really play the trick to use string type with Uncide to pass text in and out? Thanks.