1

I have the following code that instantiates a registered COM object

private dynamic server = null // Global variable.
...
Type type = Type.GetTypeFromProgID("Svr.GrpCall");
this.server = Activator.CreateInstance(type);

I can invoke methods from this COM/dynamic object just fine using very intuitive notation

string expectedResult = this.server.GroupInit(someString, someBoolean);

For single calls the performance of calling such methods through the Dynamic Language Runtime (DLR) is liveable. However, for one requirement I need to use a double for loop for thousands of records, which uses a method in the COM object that returns void

for (int i = 0; i < MAXREC; i++)
    for (int j = 0; j < MAXFIELDS; j++)
        this.server.MakeRecord(s1, s2, str);

This is MASSIVELY slow. I am aware of this and Eric Lippert's answer https://stackoverflow.com/a/7480977/626442 gives the exact cause of this performance bottle-neck.

To get around this I have attempted to define a global Action for the MakeRecord method that is under pressure

private Action<short, short, string> makeRecord;

where the plan is to use this in the for loop above. Before using this Action, I attempt to first initialise the server (as above) and then assign the makeRecord delegate to the COM method using

Type type = Type.GetTypeFromProgID("Svr.GrpCall");
this.server = Activator.CreateInstance(type);

MethodInfo methodInfo = type.GetMethod("MakeRecord");
makeRecord = (Action<short, short, string>)Delegate.CreateDelegate(type, methodInfo);

But the type.GetMethod("MakeRecord") is returning null. So, my question is,

  1. If this IS the right methodology to speed up my dynamic calls, how can I assign the COM method MakeRecord to my Action delegate?

  2. If this IS NOT the right methodology to speed up my dynamic calls, what is?

Thanks for your time.


I have also tried doing

object o = Activator.CreateInstance(type);
MethodInfo methodInfo = o.GetType().GetMethod("MakeRec");
Community
  • 1
  • 1
MoonKnight
  • 23,214
  • 40
  • 145
  • 277

1 Answers1

2

How do you know the slow behavior is due to the use of dynamic?

  • Have you tried using strongly-typed managed wrappers for the COM interfaces and calling them directly (i.e. without using dynamic and without using any reflection methods)? You can add a reference to the COM assembly itself to create the managed wrapper automatically.
  • Have you tried running your code outside the debugger? Running code in the debugger results in up to a 100:1 performance hit for method calls to native code, which includes COM interface calls.
  • Have you considered updating the interface to provide a more direct implementation of the desired algorithm, such that you can make fewer function calls in managed code?
Sam Harwell
  • 97,721
  • 20
  • 209
  • 280
  • Thanks very much for your reply. I have profiled the code and can see that it is the `dynamic` calls to the COM object that are slow. It is recognized that these call can be very slow as the DLR has to work it magic on each call (described [here](http://stackoverflow.com/questions/7478387/dynamic-and-performance)). With the 1st point do you mean creating a C# wrapper using 'Tlbimp.exe'? I have run the code in release mode & the results are the same. The COM library as it is third party and legacy. There is also no way to optimize my use of the calls as it is a shear weight of data situation... – MoonKnight Mar 26 '14 at 15:16
  • In the profiler, how did you distinguish between the overhead of `dynamic` and the cost of the method itself? If `MakeRecord` is a slow method itself, then it doesn't matter whether or not you use `dynamic` because that's not the bottleneck. – Sam Harwell Mar 26 '14 at 16:00
  • Yes, I am aware of this. The reason I know that this method is 'non-slow' is that the legacy COM library comes with an old example VB6 application. This application can call the COM methods 'directly' and this can make calls to `MakeRecord` 6000 times in 5s. When I perform the exact same operation in C# using `dynamic` this time (for the exact same data set) increases to around 1min. Again, thanks for your time... – MoonKnight Mar 26 '14 at 17:16
  • Sam, I have been away for a while before replying to your comment because I have been away looking at you profile -> ANTLR -> talk by Terence Parr -> buying book et al.! I am amazed at this work. I recently wrote a generic syntax highlighter (nothing compared to ANTLR) and have recently been asked to re-write an old C++ compiler/static analyzer for some pseudo-code used in the insurance industry, also adding different language formats... – MoonKnight Mar 26 '14 at 17:23
  • Initially I 'gulped', thinking that this was going to be tough (but fun) - then I found ANTLR! Would it be okay to email you with a few brief questions on ANTLR before I launch in to my full attack? – MoonKnight Mar 26 '14 at 17:23