|
COM and MTS Packages
By Steven Smith
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.
|
|