avalon-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Leo Sutic" <leo.su...@inspireinfrastructure.com>
Subject [Design] ContainerManager is under fire--let's find the best
Date Sun, 09 Jun 2002 13:47:36 GMT
You wrote:
>The CM's lookup/release pair remind me a lot of the new/delete pair
>--
>which we don't have in Java because the VM does the 'delete' for us.
>
>If it is ok to let the VM reclaim memory assigned to objects without 
>having much control over the process, why is there a problem applying 
>this approach to reclaiming components for a pool?
>
>couldn't the same arguments work in each case?

Robert,

the arguments are not the same. You equate a component with something
like a 
String instance - an object that is cheap and doesn't cause any harm by
being
on the heap. For example, the code:

  for (int i = 0; i < 1000; i++) {
    String s = new String ("This is String number " + i);
  }

eats up some heap space, but that is all. The rest of the system is not 
adversely affected by the String instances on the heap, as we have not
"used 
up" 1000 precious String instances. To put it another way, there is no
shortage
of Strings - use as many as you want!

However, this code:

  for (int i = 0; i < 1000; i++) {
    InputStream is = new FileInputStream ("some_file." + i);
  }

is more dangerous. As we open files without closing them, the file
handles will
remain open until the InputStreams are GC:ed. This is bad, because as
long as
those InputStreams are on the heap, they hold on to a limited system
resource -
file handles. There is no shortage of Strings, but there is a shortage
of file
handles. That's why you should call close() on all streams that you
open, 
instead of waiting for them to be GC:ed.

There are other examples of "precious" objects - for example DB
connections. 
PostgreSQL allows (by default) only a maximum of 24 simultaneous
connections. 
That's why you should call close() on your DB connections as soon as
possible. 
(Even though other DBs may have other defaults.)

I hope the above explains why I do not think GC of components can be
considered 
equivalent to GC of regular objects.

"But", you say, "all components that are "rare" and thus must be
close()'d or 
similar, they usually have a close() method, so why bother at all? It
appears 
that all objects that needs something besides normal GC already have the
extra 
mechanisms they need."

The problem with that is that in Avalon, you do not know if the
component you 
are using needs something besides the usual GC. Every component is
defined by 
its interface, but the actual implementation may vary. So you may have
an 
implementation that works fine with normal GC, and one that needs to be 
explicitly close()'d or equivalent. As the interface must be able to
accomodate 
both, you end up writing the interface for worst-case: you include a
close() 
method (or something else equivalent).

Consider, for example, that you could switch implementations of
InputStream to 
one that does not need you to call close(). Let's say this may or may
not be 
supported on your target system. So we have a FileInputStream whose
close() 
method is empty (for backwards compatibility). Right, what do you code?
Well, 
since you do not know if your code will run on a system with
no-need-to-close-
streams, you end up writing code to close the stream anyway.

The same reasoning is behind my wish for a release() mechanism. Since we
do not 
know whether the component is pooled or not, and since no suitable
automatic 
method of reclaiming components have been found (and I doubt it will be
found in
time for Avalon 6 even), we must have a release() mechanism.


> If the only reason for using pools is performance then some tuning is 
> to be expected whenever they are used (e.g. determining the pool 
> size). This tuning is going to be dependent on implementation (e.g. 
> different implementations will require different pool sizes for best 
> performance).

The GC settings are:

 1) *Brutally* difficult to tune. I do not even know if it is
    possible.

 2) Global. Tune one pool, tune all. This makes it difficult to find
    values that work. Set value A too high, and your DB connection
    pool is suffering, set it lower and some other pool starts acting
    up.

> finally, if a pool runs out of components there is nothing stopping it

> from running the garbage collector itself [though again, this would 
> need tuning -- but might make reduce the differences between VMs].

Actually, there is. How do you run the collector? The System.gc() call
is only
a *suggestion* to the VM to collect. Calling it does not guarantee GC at
all. 
And even if you do run GC, there is no guarantee that *all* unreachable
objects 
are finalized - for various reasons, the VM may leave some for the next
pass. 
Which may not happen in a while.

I hope this explains my reasoning behind my opposition to the
GC-as-component-
release line, and my strong pro-release() stance.

/LS



--
To unsubscribe, e-mail:   <mailto:avalon-dev-unsubscribe@jakarta.apache.org>
For additional commands, e-mail: <mailto:avalon-dev-help@jakarta.apache.org>


Mime
View raw message