Clemens Vasters: Enterprise Development & Alien Abductions
Thoughts about Microsoft .NET, Enterprise Services, XML and other dull and boring things.
Updated: 9/30/2002; 5:43:57 PM.

 














Subscribe to "Clemens Vasters: Enterprise Development & Alien Abductions" in Radio UserLand.

Click to see the XML version of this web page.

Click here to send an email to the editor of this weblog.

 
 

Thursday, September 12, 2002

Scream if you want to go faster: JIT Activation Pooling

Here's the core piece of one of the samples from my upcoming book. It's a lock-free, SMP safe, client-side pool for Enterprise Services JIT Activation proxies. While that may not sound like a big deal, it's indeed a key ingredient to writing lightning-fast Enterprise Services applications. In conjunction with server-side object pooling, this class will allow writing applications that will basically never pay the price of Enterprise Services (read: COM+) activation, except at application startup time. In that combination, it's just reconnect and regroup of existing instances. The JITAPool class is the secret sauce enabling you to leverage the power of LRPC/LPC and really take advantage of the performance of DCOM.

Constraint: The pool should only be used from within the Enterprise Services default context (which is true for non-transactional ASP.NET pages).


4:56:41 PM      comment []

Today's favorite aspect of EnterpriseServices: LRPC

If you have to go cross-process on a single machine in an all managed-code environment, COM Transport (via ServicedComponents) may be the way to go for speed! Fact of the matter is that COM uses LRPC/LPC for local calls. LRPC/LPC maps all marshaled data into a shared memory area and then tunnels the caller's active kernel thread into the callee's process space (!). There it picks up the marshaled data and dispatches it on the called object and takes the same way back. With that, LRPC can indeed complete a cross-process call within a single OS time slice (in practice, not only in theory), if the action is compact and doesn't involve anything that gives up the time slice directly (Overlapped I/O, WaitForSingle/MultipleObject, Sleep).

The catch with this is, that you can't realize the performance advantage unless you get around the problem that ServicedComponents are very costly to activate. When you compare the activation cost between Remoting and ServicedComponents, Remoting comes out as the clear winner by several orders of magnitude. However, when you compare the call times after activation, nothing beats LRPC: The solution for this is use just-in-time activation (JITA) on the ServicedComponent and keep the JITA proxies around for reuse. Watch this space for a little helper class that enables client-side JITA proxy-pooling. 

Today's not-quite favorite aspect of COM/Interop: PSOAInterface

PSOAInterface is the "universal marshaler" that creates in-memory COM stub/proxy pairs based on type library information. PSOAInterface is oleaut32's tool that enables VB to do "somewhat native" COM marshaling by mimicking the functionality of "midl /Oicf" on-the-fly. PSOAInterface builds and caches native COM proxies based on type libraries. The downside PSOAInterface is that it requires any interface to be Automation compatible, since that is what it was built for and that's the set of types that COM type libraries can express. When you go look at your COM/Interop exported CLR types, you'll find that they use PSOAInterface for marshaling. So, while the CLR can do a lot more types and COM can do more types than the Automation subset (all forms of native, typed arrays for instance), COM/Interop is forced through the PSOAInterface "type bottleneck".


3:09:25 PM      comment []

Replicating a post to the DM dotnet list here. The most common misconception about ServicedComponents is that they require the use of COM/Interop and really everyone has bought into that belief. And it is simply wrong.

The Enterprise Services team went a long and very smart way to separate COM Marshaling from COM Transport when they built System.EnterpriseServices and they've done it in such a smart way that only a few people seem to see that they did it. In fact, ServicedComponents make COM transport (including the LRPC mapping) an alternative way of transport that's deeply integrated with the Remoting infrastructure. However, the difference is that ServicedComponent will bypass the channel architecture and replace that with the COM channel architecture:

COM/Interop marshaling does not happen for ServicedComponents.

let me rephrase this: COM/Interop marshaling does not happen for ServicedComponents. Put differently: COM/Interop marshaling does not happen for ServicedComponents. There are two basic scenarios to look at (in a simplified form):

(a) ServicedComponent called in-process:

The instance is created by ways of CoCreateInstance from within the Remoting context interception sink setup process. This is done for COM+ being able to do all its activation magic including creating/inheriting existsing contexts. However, the managed reference to the newly created object is smuggled back into the context sink. All calls into a serviced component that are made to any method of a serviced component will be made using the managed reference. The managed reference is a transparent proxy for a context bound object. When you make a call through the transparent proxy, a context sink will be invoked, which does a very cheap loop through the unmanaged COM+ context (by passing a callback into a DoCallback method sitting on the unmanaged context) to place the context onto the call stack; the arguments and return values are never marshaled by ways of COM/Interop. They are passed natively through an IMessage object just as the Remoting context does it.

(b) ServicedComponent called out-of-process:

The remote instance is created by ways of CoCreateInstance from within a Remoting context interception sink. This is basically the same story as above. However, EnterpriseServices will divert traffic into _COM Transport_ in the out-of-process case. The difference between out-of-proc and inproc calls is this reroute is skipped in the inproc case. EnterpriseServices will invoke the interface IRemoteDispatch on the remote object (which always exists for ServicedComponents). IRemoteDispatch receives a string'ized blob. The blob contains the BinaryFormatter-marshaled IMessage from the client side, which is unmarshaled on the server-side and dispatched onto the target object. About the same happens going back (the two methods on IRemoteDistpatch both return strings). Here again, all arguments and return values are tunneled through COM Transport, but COM/Interop marshaling doesn't happen.

Prove it to yourself: You can make a ServicedComponent class that has neither a COM/Interop class-interface [ClassInterface(ClassInterfaceType.None)] nor any COM-visible interfaces [ComVisible(false)] and you will still be able to invoke this component remotely -- and it's NOT using IDispatch in that case.


12:24:12 PM      comment []

The winning numbers of evening drawing at the New York State lottery on 9/11 were 9-1-1 (CNN, Lottery). Hmmm....
10:30:47 AM      comment []


© Copyright 2002 Clemens Vasters.



Click here to visit the Radio UserLand website.

 


Send email to Clemens
September 2002
Sun Mon Tue Wed Thu Fri Sat
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30          
Aug   Oct