views:

906

answers:

3

Hello,

I am trying to minimize the performance penalty of communicating across AppDomains in the same machine. In my toy example, Class A is loaded in AppDomain 1. It creates an AppDomain 2 and loads there an instance of Class 2 (Class 2 inherits from MarshalByRef) getting back a proxy. Then Class 1 calls repeatedly a method on the proxy that returns no values.

I get the following results:

  1. No AppDomains, both classes are loaded in the same AppDomain and the first calls repetedly the method on the second (the method has no parameters): 24 million method calls/sec
  2. Two AppDomain as described above, method has no parameters or "bleeding" string parameters: 340.000 methods calls/sec
  3. Two AppDomains as described above, one serializable parameter (array of two strings): 64.000 method calls/sec

Although I understand the performance penalty between 2 and 3 (serialization), I really don't understand why I am 100 times slower from case 1 to case 2. To my understanding, once the proxy is created all subsequent method invocations must be really fast since no data are being marshalled from one AppDomain to the other. Does anybody now why communicating across AppDomains is so slow? Am I doing something wrong?

PS1. The only tip that I have on this is here: "And the cost of crossing an AppDomain boundary is embarrassing.". I was guessing he refers to serialization...

PS2. I don't count the AppDomain or Proxy creation time (my benchmarks start in the first method invocation)

PS3. I am using .NET 3.5 in a WinXP SP3 machine. I also tried .NET 4.0 Beta 1 with no significant differences.

+1  A: 

Is there any way you can call a single helper method that takes parameters about how many times you want to call the method you need? Cross-AppDomain call performance varies greatly by implementation. I believe it could be significantly better in the CLR 4.0, but I'm not fully versed on the details there.

Generally though, you want to avoid the overhead by "batching" the calls through a helper method.

280Z28
I don't see how it will help me. My Class A's method does exactly that: continuously calling object.MyMethod(). If the cost of a call in a proxy is genuinely 100 times larger than a call on a same AppDomain object, the impact in my design will be huge.
Papajohn
Call object.MyHelperMethod, which calls object.MyMethod repeatedly in the other AppDomain. If you need the performance and you assumed/required high speed cross-AppDomain calls for it, then yes, it could have a big impact on your design.
280Z28
Ohh, I see..! :-) OK, this will of course make things fast. But this example is just a toy, my real program will not call the same function 20mil times per second..! I will have to do various cross-AppDomain calls that must be fast in general.Thnanks anyway!
Papajohn
A: 

I have seen the same results. I can't explain why it is so much slower, except that it is faster then having two different processes running and communicating with each other. In my design I was faced with a similar dilemma. At the end, I have modified my design to create independent app domains; the app domain was able to do its job without the need to communicate with another app domain during execution... It would only report data when completed.

+4  A: 

If you count lines of IL involved in each scenario, you will see that the CLR is doing much more than 100 times the work when remoting. A direct invocation is just a few opcodes, but with remoting there are multiple classes involved, real/transparent proxies, security checks, serialization, yadda yadda yadda. You will need to address this through design - there is no magic bullet for improving perf through implementation.

Addys
+1 I agree with you completely. A simple direct method call is extremely simple. A method call through **remoting** is much heavier. The overhead is much larger. The only real solution is a good application design that wouldn't depend on the speed of cross AppDomain communication.
jpbochi