|
VB Component Threading Details
by Charles Carroll
special thanks to Jon Flanders, Stephen Martin and Juan
Llibre
Component written in Visual Basic are affected by some
complex threading isses we will discuss here. The "bible" for all this is:
Programming Distributed Applications with COM and Microsoft Visual
Basic 6.0
by Ted Pattison, Published by Microsoft Press.
Objects created and destroyed at the page level scale very
well. Once a session level object is created it is attached to a specific, discrete
thread. That thread can never be destroyed until all users assigned to that thread either
<%session.abandon%> or their session times out. This is the internal workings of the
ASP execution environment. Don Box wrote this fascinating detail up a couple of MSJs ago.
Objects created with a session scope, i.e.
set
session("whatever")=server.creatobject("whatever.id")
do not scale well and are affected by the threading issues
in the following way:
- You tie the Session down to a particular thread ( instead of
ASP being able to use any thread from the thread pool).
- If you place a object marked apartment into the SessionObject
you have an object which can only live and be called from the Single-Threaded
Apartment it was created in, ASP must run ALL request for that Session in that STA.
- If you don't do this (or only place Apartment Neutral Objects
in the SessionObject ) ASP will run requests for that session on the first available
thread.
So imagine - you have a four processor machine running
IIS/ASP - forty people come into your site, now each of those requests is now tied to a
specific thread, now two requests stop (are not currently making requests) - one more
comes in and gets dispatched to one of these two threads that are free, and one of the two
that stopped comes back - but another Session is using that thread - there are now free
threads that cannot be used - they are just sitting there doing nothing - while a user is
waiting for its thread to be freed. This is just one example of what can go wrong (not to
mention the additional work ASP must do to make sure this all works correctly). Overall
placing object marked Apartment into the SessionObject is a very bad thing. You are way
better off instantiating on every page. You are correct - that you cannot place an
Apartment threaded object into the ApplicationObject - which is probably what they should
have done with the SessionObject as well.
All calls that involve objects conversing must be proxied.
The proxy referring to is what the COM runtime creates in an Apartment when that Apartment
receives an interface to a COM object which lives in another Apartment.
For example - if you use a COM object which is marked
"Free" in the registry - ASP will create that object and it will live in the
Multi-Threaded Apartment (MTA), the page which is executing in a Single-Threaded Apartment
(STA) will not get direct access to the object - but will talk to the object through what
is called a proxy. The proxy looks just like the interface to the Page (has the same
methods etc), but when the page calls a method, the proxy forwards the method call
(parameters, name etc) to a COM provided channel. This channel calls what is refered to as
a stub - which again looks just like the object - but lives in the same Apartment as the
Object (in this case the MTA). Then finally the object gets called and then returns
throught the same method. This is 1000xs slower that if the object lived in the same
Apartment as the page (because of a thread switch - so switching threads you can see is
very expensive). This is just how COM works.
When a COM object is redesigned to be stateless and run under
MTX, objects in the same package are not crossing process boundaries. Different packages
are!
Run the scenarios:
Scenario 1: So if for example,
+ 100 people hit your site for a couple of pages and leave
+ 100 new people arrive in a couple of minutes
+ 200 people arrive after that and then
+ 50 people
=====
450 sessions/objects in memory with 50 !!! people on your site. And dozens or
hundred of threads that can't be reclaimed for a while
Scenario 2:
+ 100 people hit your site for a couple of pages and leave
+ 100 new people arrive in a couple of minutes
+ 200 people arrive after that and then
+ 50 people
=====
50 objects in memory because you destroyed all objects at the page level. No
threads tied up.
If it isn't Apartment Neutral (i.e. aggregates the
Free-Threaded Marshaller) - you will tie the session down to that thread - so you have to
ask yourself - is tying my sessions down to a specific thread a major performance hit -
and that really depends on how many users are hitting your site and how often. In general
I think it is a bad thing and should be avoided - unless there is no other way to
accomplish what you want - and there almost always is a way - that isn't too much work and
doesn't have any negative side-effects
This is why I have <%@enablesessionstate=false%> and a
blank global.asa. If I need an object, I create and destroy it at the page level. for
almost every page on my site and with 10,000 sessions a day and 90,000 page views we still
serve pages fast and don't get locked up very often.
 |  |  |
 |
There are many worthy charities!!. But perhaps help starving children in Africa or South America AND help Charles too.
a $5 tip buys him lunch at McDonalds,
a $20 tip buys his kid Hitoshi a new computer game,
a $39 tip buys his daughter Michiko a few nice outfits.
See our donor list.
|  |
 |  |  |
|
|
|
|