0

I have read this and this and was wondering if I use in C# functions from unmanaged C++ library via C# wrapper of this library, is there going to be any difference in performance compared with the same program, but written fully with unmanaged C++ and the C++ library? I am asking about crucial performance difference bigger then 1.5 times. Notice I am asking about the function performance of the C++ library only(in the two ways - with and without the use of C# wrapper), isolating the other code!

After edit:

I was just wondering if I want to use C++ dynamic unmanaged library(.dll) in C# and I am using wrapper - which is going to be compiled to intermediate CIL code and which is not. I guess only the wrapper is being compiled to CIL, and when C# want to use C++ function from the library it is just parsing and passing the arguments to C++ function with the use of the wrapper, so there will be maybe some delay, but not like if I write the whole library via C#. Correct me if I am mistaking please.

Community
  • 1
  • 1
nicksona
  • 326
  • 2
  • 13
  • 4
    Have a look at this: http://ericlippert.com/2012/12/17/performance-rant/ – Wai Ha Lee Dec 14 '15 at 12:28
  • 2
    @mecek Say that to your customers when doing of-the-shelf software. – Ralf Dec 14 '15 at 12:32
  • 2
    Additionally to the test-it-yourself-rather-than-asking ideas already pointed out, your question is extremely abstract (on the lines of what language is faster) and as such not really answerable. C++ has some advantages, but also C#; even when talking about pure performance. It depends upon what you are doing and how you are doing it. – varocarbas Dec 14 '15 at 12:34
  • Look after edition. C# is not as fast as C++, becouse it is compiling(like java to bytecode) to intermediate CIL code. So I wonder is there slight performance difference in using C++ library via C# wrapper. I know if I use C# library(fully written with the use of C#), equivalent of unmanaged C++ it will be slower(noone can convince me the opposite), of course if the algorithms are the same. – nicksona Dec 14 '15 at 12:56

1 Answers1

5

Of course, there is overhead involved in switching from managed to unmanaged code execution. It is very modest, takes about 12 cpu cycles. All that needs to be done is write a "cookie" on the stack so that the garbage collector can recognize that subsequent stack frames belong to unmanaged code and therefore should not be inspected for valid object references.

These cookies are strung together like a linked-list, supporting the scenario where C# code calls native code which in turn calls back into managed code. Traversed by the GC when it collects. Not as uncommon as it sounds, it happens in any GUI app for example. The Click event is a good example, triggered when the UI thread pinvokes GetMessage().

Not the only thing that needs to happen however, in any practical scenario you also pass arguments to the native function. They can require a lot more work to get marshaled into a format that the native code can understand. Arrays in particular, they'll need to get pinned if the array elements are blittable, that's still pretty cheap. Gets expensive when the entire array needs to be converted because the element is not blittable. Not always easy to recognize, a profiler is forever the proper tool to detect inefficient code.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • You mean C# and C++ have theoretically separate memory spaces and the C# garbage collector is working only for C# code(like it should) and when C# code pass parameters to C++ function all of them are being converted to unmanaged C++ equivalent. I wonder if you pass array pointer from C# to C++ function what will happen - the object memory is being managed by C# GC, but after the call you will have pointer in C++ unmanaged code. If while you are executing the function from C#(multythreaded) delete the C#'s pointer and there is only pointer in C++ - is GC will be able to free the memory? – nicksona Dec 14 '15 at 13:15
  • 1
    "Separate memory spaces" is not the right mental model. There is no fundamental difference between managed and unmanaged code, they get converted to plain CPU instructions in both cases. The only detail that matters is that the GC can find object references back in code that was generated by the jitter. And can't find them back in code that was generated by another tool, like a C++ compiler. Messing with passed array pointers in a pinvoked function is just a plain bad idea. You can easily corrupt the GC heap, the eventual crash that this produces is *very* hard to diagnose. – Hans Passant Dec 14 '15 at 13:21
  • 1
    Continued: the extra thing the jitter does that a C++ compiler doesn't do is that it generates a table when it converts a method. That table says where to look for an object reference. It indicates the stack frame slot or the CPU register that has the reference and at what address that reference starts and stops being valid. The GC needs that table to accurately find the objects. – Hans Passant Dec 14 '15 at 13:27
  • I just didn't understood - I can pass array pointer to C++ library and I will be able to fill the C# array(or the object) from within the C++ function and there will be no problem, except if I delete the C# pointer to the array(multythreaded) while the C++ function is filling the array, or it is NOT RECCOMENDET at all to pass pointers, insted of this I must marshal(convert) every array or variable passed to the C++ lib, because in this way it will be very time comsuming for my needs. – nicksona Dec 14 '15 at 13:32
  • 1
    Arrays are managed by the GC. And pinned by the pinvoke marshaller. You have to shoot your left foot with a cannon to get it to make the pointer invalid while the C++ code is executing. It is technically possible, you'd have to micro-optimize yourself into trouble. Or storing the pointer in the C++ code and continue to use it later, you can never not notice that mistake. Click the Ask Question button when it happens. – Hans Passant Dec 14 '15 at 13:37