Overhead of COM+ Services in .NET
By Peter A. Bromberg, Ph.D.
Printer - Friendly Version
Peter Bromberg

I'm fortunate enough to work with some pretty sophisticated developers. We have a .NET team with a diverse background; some, like myself, come from the VB6.0 / Windows DNA school and have been going through the OOP .NET learning curve and have become proficient in C# as their preferred .NET language of choice. Others came from the JAVA space - they already were well - schooled in OOP principles (sometimes I think too much, since in .NET, it's possible to flatten out the object model considerably and still achieve OOP-oriented objectives). There is a pretty good interchange of ideas, and developers help each other. A highly productive environment in which to learn, work and grow.



One of the things I've noticed, especially from the former JAVA guys, is that they come from an environment (not usually on the Win32 platform) where they are used to having the kind of application servers that scale with multiple instances of components acting as a monolithic instance. This is done both for failover reasons as well as to have more computing power handling large amounts of traffic. Naturally, their first look at Windows Component Load Balancing tells them it's analogous to this stuff they are accustomed to from the JAVA space, and that's where the problems begin.

Application Center Server 2000 (ACS) is designed to handle component load balancing (CLB), monitoring, and automated application deployment (not just CLB). There are probably cheaper ways to do load balancing, but when you add in the management features, some companies find that they save money and time by using ACS.. ACS, as opposed to Windows 2000 DataCenter Edition, which requires a minimum of 8 processors, works just fine with commodity single - and dual-proc servers. It also allows you to configure NLB on Windows 2000 Server. For some companies, this could save some costs over the licensing costs of Windows 2000 Advanced Server, depending on your server environment configuration.

I've seen at least one situation where the ex - JAVA guys believed (understandably) that if they made their .NET components Enterprise Services components, installed them in the GAC and had them run in COM+ Services, that they would be able to use this environment in the same way as they did with their Beans and other JAVA stuff through IBM WebSphere or whatever - like Component Load Balancing. I've railed continuously about the overhead of COM+ and how by using Network Load Balancing (NLB), which comes with Windows Advanced Server and higher (or can be configured on Windows 2000 Server using ACS as mentioned above), you can have multiple copies of the application running on a web farm and achieve similar scalability results, and you don't need COM+, as long as your calls are being made over the web, or via TCP, which these days is more often than not the case. And, let's not forget that TCP can be remoting framework calls over the TCP Channel into the NLB "Farm" that have nothing to do with the web at all.

Throughput

Throughput performance declines when making any kind of call across a network. Using CLB always incurs this cost and this needs to be accounted for in making cluster architecture decisions. To give some perspective on this, the following data (from one of the CLB Whitepapers) shows the number of calls per second on a single threaded Visual Basic 6 COM component that returns “Hello, world” as a string property. The client is early bound and doesn’t release references between calls to retrieve the property.

Scenario Calls per Second Relative Speed
COM+ Server Application, run over a 10BaseT network 625 1.0x
COM+ Server Application, Out Proc, same box 1923 3.08x
COM+ Library Application, In Proc, same box 3333 5.33x

It’s clear that calls over the network yield slower throughput than calls to software installed on the same computer. For this reason, CLB does not make a great solution where throughput is the most important consideration. In this case it is better to install the COM+ components locally on the Web-tier cluster members, avoiding cross-network calls. CLB support is lost but load balancing is still available through NLB. And as we will see in a moment, in the case of a .NET - based solution, careful consideration should be given to whether the components should be installed in COM+ at all, since NLB could care less whether your components are in COM+. With NLB, we can have cookieless sessions via ASP.NET and we can also use the SQL Server Session State service with a simple web.config entry and a database script. In addition, it is possible to pass credentials data to our Remoting Framework components over NLB.

Network Load Balancing (NLB) distributes IP traffic to multiple copies (or instances) of a TCP/IP service, such as a Web server, each running on a host within the cluster. Network Load Balancing transparently partitions the client requests among the hosts and lets the clients access the cluster using one or more “virtual” IP addresses. From the client’s point of view, the cluster looks like a single server. As enterprise traffic increases, network administrators can simply plug another server into the cluster. Provided that DTC - type transactionality across components is not absolutely necessary and the components are written to be stateless, great economies of scale can be obtained at a much lower cost using relatively inexpensive 2 or 4 proc boxes for the farm.

In my article about   Implementing .NET Role-based security without COM+ , I showed how it is possible to eliminate the overhead of COM+ in order to achieve role-based security with pure .NET code by using the LogonUser API in combination with attribute-based or imperative security checks. And, contrary to what some may believe, it is possible to make such calls via the Remoting Framework over the TCP Channel by employing the CallContext Class, deriving from ILogicalThreadAffinative, to pass out-of-band credentials parameters such that the LogonUser API can even be called on the remote server without messing up interface or method signatures. I had read enough articles by some of the pros on MSDN to convince me that my suspicions about COM+ overhead were correct, and so I stand by my position:

Unless your .NET application needs intra-component transactions, or has components that are very expensive to instantiate, you don't need COM+ services.  If all you need is role-based security, consider using the LogonUser API.

In fact, most of what you would want to achieve by calling LogonUser() could be accomplished, much more simply and with less overhead, in the <identity> section of web.config. Just use Windows authentication and impersonate, or - now you can even configure the identity under which aspnet_wp will run using Microsoft's new security enhancement tool (more on this one soon!).

NOTE: If you are using the System.Data.SqlClient namespace, be aware that this class already uses System.EnterpriseServices.ResourcePool internally for connection pooling, so unless your component is very complex or needs transaction services, installing it in COM+ may be, well - kind of "overkill".

The Common Language Runtime can instantiate 10 million objects a second on a typical machine. The jury may still be out, but I doubt you need "Just in Time Activation", and you certainly don't need "Object Pooling" with fast, lightweight .NET assemblies. If your components use transactions, you can control these off the Connection Object in ADO.NET, or handle it directly in Sql Server with BEGIN TRAN / COMMIT TRAN, etc.

Enough said; you are free to disagree, this is just my opinion. My point is: do your homework, get the facts, figures and arithmetic, and make informed architectural decisions as a developer. Do some tests, and evaluate. Make sure you're comparing apples to apples. Above all, don't accept marketing "hype" as gospel.

With that in mind, I decided to write a small DB Component that did nothing but run the CustOrderHist stored procedure in Sql Server against the ever-popular Northwind sample database, and return a SqlDataReader. I created a Winforms Test app that calls into the DB component 10,000 times and records the elapsed time for the run. I compiled a version of the component deriving from Enterprise Services with AutoDual and Autocomplete, and installed it in the GAC and COM+ as a Library Application. I compiled a separate version of the component with no COM+ attributes, just pure C# .NET code. Aside from these differences, the components are identical. I thought readers might be interested in my results. As you can see in the chart below, I did three runs on each test component, and averaged the results.

 

COM+ Serviced Component, GAC'ed Installed as Library in COM+ : 10,000 Calls
Run Number Elapsed Time (Sec.)
First 35.25
Second 34.84
Third 34.75
Average: 34.94
.NET Only, No COM+ Attributes in classes, 10,000 Calls:
Run Number Elapsed Time (Sec.)
First 18.32
Second 17.85
Third 18.12
Average: 18.09
Performance Cost, COM+: 93.11%
COM+ overhead nearly doubles execution time.

 

While this cannot be considered to be an authoritative test scenario, the difference is so dramatic that it's sufficient to confirm my own belief that COM+ Services is something most developers really don't need. I might add that the above represents the best times I have obtained for the COM+ installation; subsequent tests with various settings such as Object Pooling and Just In Time Activation gave even worse results for COM+.

Those readers who are still using VB 6.0 might be interested to know that an equivalent component and Forms-based test app I wrote in VB 6.0 with the component being a COM DLL, averaged 38.5 seconds for the above test run. Comments and criticism are always welcome here at our Eggheadcafe.com forums. In particular, I would be interested in hearing from other developers who have actually conducted their own test scenarios, since aside from an excellent piece by Shannon Pahl of MS, "Understanding Enterprise Services in .NET", and the articles I quote in my previous article referenced above, all of which more or less confirm the information I present here, there is literally NO documentation about this in any of the literature that I've been able to find.

As is my custom, I have provided a downloadable ZIP file containing the full solutions for both the NETDBComponent and the COMPlusDBComponent, each with its own Winforms test harness that kicks off the 10,000 call test and records the elapsed time in seconds, using the System.DateTime.Now.Tick which records time in 100 nanosecond resolution. There are two batch files in the bin/Release folder for the COM+ solution "Regme.bat" and "UnRegme.bat" which will do (or undo) your Gacutil.exe and your Regsvcs.exe installations for convenience.

Summary:

COM+ Services is a sophisticated COM - based infrastructure whose primary value to the developer lies in multi-component transaction control with object instantiation and pooling services. There is ample support for these COM+ services in the .NET Framework through the System.EnterpriseServices namespace as well as attributed programming features. Component Load Balancing (CLB), available on Application Center Server, enables you to run COM+ Services components on multiple machines with failover and have the components both appear and function as a single "machine". However, because of the overhead of COM+ and the fact that expensive cross network calls are necessary with CLB, it is probably best advised to be used for Database and other back-end applications. If your objective is speed and scalability, and you do not need transactions, it would be wise to compare the throughput using a pure .NET solution, even if you need role - based security in your application. Such solutions can be hosted through Network Load Balancing for cost - efficiency and the best possible throughput and scalablity, and COM+ is neither necessary nor particularly desirable in such configurations.

Download the code that accompanies this article


Peter Bromberg is a C# MVP, MCP, and .NET consultant who has worked in the banking and financial industry for 20 years. He has architected and developed web - based corporate distributed application solutions since 1995, and focuses exclusively on the .NET Platform.