• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1172
  • Last Modified:

Calling an unmanaged DLL from C# (for performance)

I have a situation in which I need to get a lot of system level data from the Win32 API. There is a .NET API made specifically for getting this data and it produces correct results. However, it is pretty slow. I needed to speed up the performance, so I wrote a lot of in unmanaged code in VC++. The bottom line is that when comparing the retrieval of data, and I have meticulously benchmarked it, the unmanaged code is 85% faster. In fact, the amount of data that will bet gather can range from 640KB to maybe a 100MB, and my 85% speedup is comparing the unmanaged code gathering the data AND writing it out, while the C# version merely reads it.

I've compared my C++ code to the Reflector output of the .NET API that is equivalent, and I think I know why the .NET implementation is so slow, but in any event I need to use this unmanaged code. The thing is, I'll be doing this retrieval from a .NET Windows Service.

What is the best way to call my unmanaged code from C# to get the best performance? Basically, I *ultimately* want to populate a .NET DataTable with this data. There can be anywhere from 400 - 100,000 rows of data and, again, 640KB-100MB of data. I guess the strategy is to reduce the amount of marshaling? (The C++ data is currently stored in a class but can be changed to a struct)

Anyway, what is the best way to do this to preserve performance? Doing a managed C++ DLL and then calling the Win32 code could be an option, though I've never used managed extensions for C++. But would that do much in the way of performance over calling the unamanged stuff from C#, since either way there its crossing the border between managed and unmanaged?

(Just to clarify, I know about P/Invoke. Its not a question of whether its possible to do this but what is the best method from a performance perspective.)
  • 2
1 Solution
Without knowing any details of what you are doing, I would not comment on any "best" way of doing something.  In general, however, you seem to understand the issues involved.  but to get a discussion going, I have these comments:

1) Keep as little data as possible crossing the managed/unmanaged boundary.
2) Keet the data crossing the boundary as simple as possible to avoid complex marshaling.
3) Since you have been able to compare the Reflected .NET code against your C++ code, is there a way to write .NET code yourself that works around the performance limitations that you identified in the framework code?  I have used that technique with success.  Not really feasible if it's too far down in the .NET guts.
4) You are dealing with a fairly big chunk of data.  What kind of timing are you looking at when you say the unmanaged code is 85% faster?  There's a good chance you lose that advantage marshaling multiple MB of data.
NetworkArchitekAuthor Commented:
Thanks for the reply. For #3, that's not really an option because for one, the .NET API is doing a lot of marshaling and I would have to recreate what I've done but still do a whole lot of Interop.

For #4, in terms of timing, my unmanaged code runs (say for a larger dataset of about 10MB-20MB) it runs in several seconds (say 10-15 seconds), while the .NET code takes a 1-2 minutes (even if you rerun the function again to dismiss the problem of JIT compilation). Also, I will ultimately do filtering on the data which will make my unmanaged code's performance be much better but the way the .NET API's method works, it will not get as much benefit from filtering.

I think taking the output from the unmanaged, making it like a CSV and compressing it, then load it/decompress from C# would be faster than just letting C# do it through the .NET API (basically, the .NET API makes a *lot* of unnecessary calls to LoadLibraryEx() which is a primary reason why it is soooo slow). However, I don't want to go that route.
What do you intend to do with the .NET DataTable?  Is it reasonable to just do that whole part of your app in unmanaged code and forget .NET?  Then you can just do a simple PInvoke call to execute that functionality and not have to worry about marchaling all the data back to managed space.
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Introducing Cloud Class® training courses

Tech changes fast. You can learn faster. That’s why we’re bringing professional training courses to Experts Exchange. With a subscription, you can access all the Cloud Class® courses to expand your education, prep for certifications, and get top-notch instructions.

  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now