The ASPSmith Articles, ASPAlliance.com

COM and MTS Packages

By Steven Smith
http://www.aspalliance.com/stevesmith/articles/mtspackageboundaries.asp

Recently at a client of mine I migrated an application using COM and MTS from one webserver to another. The new server was the production webserver for the company and already had a couple major applications running on it using the set of COM objects that I had developed over the last year. The application I was moving was in essence a legacy application built on COM objects that were written by the client themselves, using standard object oriented practices. As such, the objects were completely stateful and did not interact with my objects at all.

I copied the website itself to the new box, set up the server, and began installing the COM objects. I had to move quickly because this was a live site and they wanted minimal downtime (although getting it set up and running as just an IP address, then transferring the DNS and leaving both boxes up for a few days would have been the best choice for no downtime). Because the legacy components did not support MTS and did not interact with my components, I chose to install them in their own package. Once I did, after some minor debugging, everything worked great. As soon as the site was up and running, the little green balls started spinning, and I started getting as many as 20 legacy objects in use at a time. My components never had more than 5 or 6 active at once, so I thought that the difference was due to the stateless nature of my COM objects versus these stateful ones. I was wrong.

An hour later...

...until I started looking at the box some more a little later. I had been monitoring the database, our usual bottleneck, using Perfmon and had not seen any major hits, although the number of connections seemed much higher than usual. However, once I took a look at the cpus on the webserver, I saw that it was pegged at 100%. At this point I started looking around, and noticed that things were running terribly slow on the server, including my existing applications. I looked around a bit on the server and discovered that one of the legacy application's COM components was installed in my components' package. It had been on the server already when I had moved the other objects, and so was not installed in their package. Recalling MTS design principles I've read elsewhere, I deleted the object from my package and reinstalled it in the legacy application's package. Immediately, the cpus on the box dropped to < 10% (normal), the legacy app's COM components all started maxing out at 3 or 4 active at a time, and the database connections dropped by about 20. The component I had moved had been the legacy app's database access component.

What happened

In case you haven't figured it out already, the problem was the cross-package calling of components. The legacy objects I had migrated were sitting in one package, in their own memory space, and every time they were called and had to access the database, they were making a call across package boundaries to a database access component (a stateful one at that) in another package. This took time and effort because of the marshalling required to move data from one package to another. Obviously for a data access component, ALL data coming into or out of the database to these legacy components had to be marshalled. And since the data access component was stateful, a database connection was maintained for all the time this marshalling was taking place, which was using up valuable database server resources.

The lesson here is, keep your components together in the same package if they make frequent calls to one another. For seldom used components, a separate package is fine, but definitely if you are using an n-tier architecture, with data access components and business layer components, do NOT separate them across packages by layer, because every call from the business objects to the data access objects will involve marshalling and your performance will suffer dramatically.