On 06.07.2022 22:49, Rick McGuire wrote:
On Wed, Jul 6, 2022 at 3:03 PM Rony <rony.flatsc...@wu.ac.at> wrote:
While debugging potential memory leaks I could narrow one down to the
currently not tested
hypothesis that if interpreter instances get terminated it may be the case
that either the
.local contained objects or the destination objects of the .local monitors
do not release the
references such that no uninit method runs.
Background: in BSF4ooRexx whenever a ScriptEngine instance gets created an
ooRexx interpreter
instance gets created in which the .local monitors get redirected to Java‘s
System.in,
System.out and System.err. This occurs by wrapping up these Java objects as
BSF objects which
then get used to set the destinations for the .input, .output, .error,
.traceoutput and
.debuginput monitors. Upon termination of these ooRexx interpreter instance
these BSF objects
should get unreferenced such that their uninit methods can run which remove
the reference to
their peer Java objects in the Java registry, allowing them to be garbage
collected on the
Java side. This seems to not happen.
After having come up with a Java registry analyze class plus a garbage
collector BIF on the
ooRexx side I have become able to get a raw overview about the area where
running hundreds, if
not thousands of ooRexx interpreter instances (each JSP request will cause
an ooRexx
interpreter instance to be created to process the Rexx-JSPs) causes
continuous memory
consumption on the Java side. Carrying out the redirections of the .local
monitors manually
to and from Java shows that the reference counting via the uninit works and
no memory leaks occur.
So, is it possible that either .local or the destination objects of the
contained monitors do
not get freed if an ooRexx interpreter instance gets terminated? (Thinking
about this, I need
to verify tomorrow that the instances get explicitly terminated, did not
double-check that today.)
O.K. the Rexx interpreter engines do not get terminated, which explains the ever growing memory
consumption and over time slow-down! This is good as then it is clear that the problem is mostlikely
not rooted in ooRexx, but either in BSF4ooRexx or (more likely) in the taglib that causes the Rexx
interpreter instances to be created (which each needs to be cached until the entire JSP got processed).
Here a glimpse to the relevant debug info (after some stress tests) coming from the Java side, where
"REXX_ENGINE" refers to Rexx interpreter instances referrable from Java, and "REXX_PROXY" refers to
Rexx objects boxed in Java RexxProxy objects:
"RexxCleanupRef Report"
RexxCleanupRef [2022-07-07 14:49:04.755000000] [State as of:
2022-07-07T14:49:04.755]
RefKind: Instances: Finalized: Not Yet Finalized:
-----------------------------------------------------------------------
[TEST].......: [ 0] [ 0] [ 0]
[REXX_ENGINE]: [ 3,579] [ 0] [ 3,579]
[REXX_PROXY].: [ 35,789] [ 35,211] [ 578]
-----------------------------------------------------------------------
Totals.......: [ 39,368] [ 35,211] [ 4,157]
So it shows that the Rexx interpreter instances in that process do not get terminated, because they
do not get finalized on the Java side (there are still Java references in existence).
(It is actually quite amazing how performant ooRexx still is under such heavy
load conditions.)
The reference to the .local directory is most definitely released upon instance termination. Note,
however, that this happens AFTER the end-of-instance garbage collection and uninit pass, since it
is necessary to run the uninit methods in a fully functional interpreter instance. And NO, adding
an additional garbage collection cycle after that is not the answer. GC cycles are very expensive
and really should be avoided as much as possible.
Yes, indeed!
In this particular case (debugging possible memory leaks) it is sometimes really necessary to be
able to run gc right before starting a new test cycle. The other use case would be in situations
where one has 7/24 programs that do not create too many objects, but if so pinning down system
resources such that when going out of scope it may be - under edge-cases, exceptional use cases -
important to have it available. (It is like in the Java case where System.gc() allows for having the
garbage collector execute which is very helpful in debug scenarios, but otherwise never really
needed. But having this method available is important.)
[If documenting the warning clearly and pointing at debugging in the context of external pinned
resources may be sufficient to have programmers only use it in debugging and edge cases so not to
negatively impact ooRexx performance.]
Anyway, sorry for the noise and thanks for the consideration!
---rony
_______________________________________________
Oorexx-devel mailing list
Oorexx-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/oorexx-devel