In .NET there are several places when you must leave managed code and enter the realm of unmanaged a.k.a. native code. To name a few:
- extern dll functions
- COM invocation
There are always comments about overhead that jump from one side to another causes, and my question here is if anybody MEASURED exact overhead that is happening, and can explain how it can be calculated. For example, maybe byte[] can be converted to IntPtr or even to byte* in .NET and help marshaller save some CPU cycles.
[I see I didn’t really answer the question about how you would measure; the best way to measure is just with some instrumentation, either with the instrumentation classes (see: http://msdn.microsoft.com/en-us/library/aa645516(v=vs.71).aspx) or even with something as simple as placing in some timers around whatever calls you’re interested in. So, in the crudest form, when we were trying to find the performance hit taken, for instance, in our call between C# and ATL COM, we would just place timers around an empty function call we would start a timer, run in a tight loop between C# and the empty ATL COM function, do enough loops that we were able to get reasonably consistent answers between runs, and then do the exact same thing in C++. Then, the difference between those two numbers is the overhead for making the call across that boundary.]
I don’t really have any hard numbers, but I can answer from previous experience that as long as you use things in an efficient way, C# performs with very little, if any, overhead beyond what one might expect in C++, depending on the exact nature of what you are trying to do.
I worked on several applications that collected very large amounts ultrasonic data through very high frequency (100MHz-3GHz A/D boards) and by doing certain things, as you suggest, (things like byte[] arrays allocated in managed code and then locked down as pointers and passed as buffers for the data; transferring large amounts of data and processing it for imaging various parts).
Way back when, we communicated with C++ code to VB6, and we would wrap the C++ in ATL Simple COM objects, and pass pointers back and forth when needed for data and imaging. We practiced similar techniques much later with C# in VS.NET 2003. Also, I have written a library for a question here that allows for massive unmanaged data storage that can provide support for very large arrays and array operations, as well as even a lot of LINQ-type functionality! Using array fields instead of massive number of objects . (note: there are some issues with the reference counting that were in the latest version, and I have not yet tracked down.)
Also, I have done some interfacing using ATL COM with the FFTW library in order to perform high-performance DSP to good effect, although that library is not quite ready for primetime, it was the basis of the spike solution I created for the link above, and the spike gave me most of the information I was looking for to complete my much more full-blown unmanaged memory allocator and fast-array processing supporting both externally allocated as well as unmanaged allocations from the unmanaged heap, which will eventually replace the processing that currently exists in the FFTW C# library.
So, the point is, I believe the performance penalty is very overblown, especially with the processing power we have these days. In fact, you can get very good performance if you just take care to avoid some of the pitfalls (like calling lots of little cross-boundary functions instead of passing buffers, or multiple allocations of strings and such) using C# by itself. But when it comes to high-speed processing, C# still can fit the bill for all of the scenarios I’ve mentioned. Does it take a little forethought, yes, sometimes. But the advantages gained in development speed, maintainability, and understandability, the time I spent figuring out how to get the performance I need has always been far less than the amount of time it would have taken to develop primarily or completely in C++.
My two bits. (Oh, one caveat, I mention ATL COM specifically because the performance hit you took when using MFC was not worth it. As I recall it, it was about two orders of magnitude slower when calling out via an MFC COM Object versus the interface on the ATL one, and did not meet our needs. ATL on the other hand was only a smidge slower than calling the equivalent function directly in C++. Sorry, I do not recall any particular numbers offhand, other than that even with the large amounts of ultrasonic data we were collecting and moving around, we did not find it a bottleneck.)
Oh, I found this: http://msdn.microsoft.com/en-us/library/ms973839.aspx “Performance Tips and Tricks in .NET Applications”. I found this quote very interesting:
Sample section titles: “Make Chunky Calls”, “Use For Loops for String Iteration”, “Be on the Lookout for Asynchronous IO Opportunities”.
Some snippets from the referenced Fast Memory Library:
in
MemoryArray.csfrom
MemoryArrayEnumerator.cs