This is the planned implementation of gc() which
* always runs in a debug version of ooRexx (.RexxInfo~debug=.true)
* does *not* run in a release version of ooRexx (.RexxInfo~debug=.false) to
cater for Rick's
preoccupation; however, there is an overrule possibility if the argument
"force" is supplied for
edge cases, using it must be deliberate for a release version. This should
at least rule out
using it mistakingly in the release version, if used for debugging, but not
meant for release.
The planned description of gc() would be:
gc(---+-------------+---)
| |
+---"Force"---+
Returns /.true/ if the garbage collector was called, /.false/ else. This
function should be used
with great care as explicitly invoking the garbage collector imposes quite a
burden on a running
system and can severely affect applications. Therefore, garbage collection
invocations should be
best left to the interpreter. If invoked from a debug version of ooRexx
(.RexxInfo~debug=.true),
the garbage collector will always be called. If invoked from a release
version of ooRexx
(.RexxInfo~debug=.false), the garbage collector will not be called, unless
the optional argument
“force” is supplied.
Enclosed you'll find the diff.
Here a little test program that invokes the garbage collector 10,000 times and compares this to
invoking 10,000 times the reverse() BIF on a debug version of ooRexx:
d1=.dateTime~new
count=10000
t1=test_gc(count)
t2=test_reverse(count)
d2=.dateTime~new
say "test_gc("count") :" t1 "->" t1/count "per call"
say "test_reverse("count"):" t2 "->" t2/count "per call"
say "total duration :" d2 - d1
::routine test_gc
use arg count
d1=.dateTime~new
do count/2
call gc -- call the garbage collector
call gc "force" -- call the garbage collector
end
return .dateTime~new - d1
::routine test_reverse
use arg count
d1=.dateTime~new
do count/2
call reverse '' -- call reverse()
call reverse '' -- call reverse()
end
return .dateTime~new - d1
Running this on a quite old PC yields:
G:\test\orx\gc>rxenv rexx test_gc_speed.rex
test_gc(10000) : 00:00:00.971000 -> 00:00:00.000097 per call
test_reverse(10000): 00:00:00.000000 -> 00:00:00.000000 per call
total duration : 00:00:00.971000
G:\test\orx\gc>rxenv rexx test_gc_speed.rex
test_gc(10000) : 00:00:01.005000 -> 00:00:00.000100 per call
test_reverse(10000): 00:00:00.004000 -> 00:00:00.000000 per call
total duration : 00:00:01.009000
G:\test\orx\gc>rxenv rexx test_gc_speed.rex
test_gc(10000) : 00:00:00.987000 -> 00:00:00.000098 per call
test_reverse(10000): 00:00:00.004000 -> 00:00:00.000000 per call
total duration : 00:00:00.991000
G:\test\orx\gc>rxenv rexx test_gc_speed.rex
test_gc(10000) : 00:00:00.972000 -> 00:00:00.000097 per call
test_reverse(10000): 00:00:00.008000 -> 00:00:00.000000 per call
total duration : 00:00:00.980000
Any comments, feedback?
---rony
On 29.08.2025 11:59, Rony G. Flatscher wrote:
Thank you all very much for your feedback (also to those who reacted with a
direct e-mail to me)!
My take away currently is that
* using a keyword is not really acceptable (it really looks a little bit
awkward)
* restricting the invocation by a predefined number may not be possible if
programs run 7/24
(where this feature might be important in edge cases)
* the hints at popular languages that allow for invoking the garbage
collector freely, making it
the responsibility of the programmer to use it cautiously and only, if it
is needed (e.g. for
unpinning non-Rexx resources that are held in Rexx objects that have gone
out of scope)
* one should clearly document and warn about misusing this feature pointing
out at potential
runtime performance implications (like in other programming languages)
---rony
On 26.08.2025 22:28, Rony G. Flatscher wrote:
There is a new library for ooRexx in development by one of my students, where objects from the
other side get proxied in registries. For debugging, it is necessary to be able to kick off a
garbage collection run.
However, as has been pointed out and discussed, it has been seen as dangerous for the performance
of ooRexx programs if ooRexx programmers use such a feature wrongly (e.g., too many times at the
wrong place, etc.).
My take would be that if programmers are made aware of that potential problem and strongly
advised not to use it for regular programs, only for situations where it becomes important that
external resources get freed that are held by Rexx objects that became garbage but do not get
garbage collected in a timely manner.
Maybe an approach like this can be acceptable?
* define a gc() built-in function that works by default in a debug version of
ooRexx (i.e.,
RexxInfo~debug yields .true) and returns .true to indicate that the BIF got
carried out,
* invoking some gc() on the release version of ooRexx (i.e., RexxInfo~debug
yields .false) does
not invoke the garbage collector and returns therefore .false.
o for very rare, special situations (like freeing external resources as
timely as possible
if Rexx objects pinning them down turn to garbage) it may make sense to
allow gc() to be
run on a release version; in order to make this explicit one could
think of allowing an
argument like "EMERGENCY" (intentionally in uppercase and spelled out),
but only for the
release version, which would indeed invoke the garbage collection on a
release version as
well and then return .true to indicate it. This would inhibit a
mistakenly usage of gc().
If one leaves the gc() invocation from the debug version, it would not
run the garbage
collector by default on a release version. If, however, a programmer
needs a garbage
collection in the release version, it must be "cumbersomely" invoked,
such that this can
only happen intentionally.
What do you think? Any comments?
---rony
Index: interpreter/expression/BuiltinFunctions.cpp
===================================================================
--- interpreter/expression/BuiltinFunctions.cpp (revision 13011)
+++ interpreter/expression/BuiltinFunctions.cpp (working copy)
@@ -1,7 +1,7 @@
/*----------------------------------------------------------------------------*/
/*
*/
/* Copyright (c) 1995, 2004 IBM Corporation. All rights reserved.
*/
-/* Copyright (c) 2005-2024 Rexx Language Association. All rights reserved.
*/
+/* Copyright (c) 2005-2025 Rexx Language Association. All rights reserved.
*/
/*
*/
/* This program and the accompanying materials are made available under
*/
/* the terms of the Common Public License v1.0 which accompanies this
*/
@@ -2982,7 +2982,6 @@
return SystemInterpreter::popEnvironment(context);
}
-
/**
* Qualify a stream name.
*/
@@ -3000,6 +2999,45 @@
return new_string(qualified_name);
}
+/**
+ * Invoke the garbage collector.
+ */
+BUILTIN(GC)
+{
+ const size_t GC_Min = 0;
+ const size_t GC_Max = 1;
+ const size_t GC_force = 1;
+
+ check_args(GC);
+
+ RexxString *force = optional_string(GC, force);
+
+ bool bRunGC=false; // default to not run in release mode
+
+ if (force != OREF_NULL) // argument given, check whether argument starts
with "F" for "force" ...
+ {
+ const char *forceData = force->getStringData();
+ if (forceData[0]==0 || (forceData[0]!='f' && forceData[0]!='F'))
+ {
+ // 40.904 function_name argument argument_number must be one of
values; found "value".
+ reportException(Error_Incorrect_call_list, "GC", IntegerOne,
new_string("force, Force, F, f",18), force);
+ }
+ bRunGC=true; // run the garbage collector in release mode
+ }
+
+#ifdef _DEBUG // in debug mode always run the GC
+ bRunGC=true;
+#endif
+
+ if (bRunGC)
+ {
+ memoryObject.collectAndUninit(false); // keep stack
+ return TheTrueObject; // indicate we called the garbage collector
+ }
+ return TheFalseObject; // indicate we did not call the garbage
collector
+}
+
+
// the following builtin function table must maintain the same order
// as the BuiltinCode type defined by the RexxToken class.
pbuiltin LanguageParser::builtinTable[] =
@@ -3085,5 +3123,6 @@
&builtin_function_ENDLOCAL ,
&builtin_function_SETLOCAL ,
&builtin_function_QUALIFY ,
+ &builtin_function_GC ,
};
Index: interpreter/parser/KeywordConstants.cpp
===================================================================
--- interpreter/parser/KeywordConstants.cpp (revision 13011)
+++ interpreter/parser/KeywordConstants.cpp (working copy)
@@ -1,7 +1,7 @@
/*----------------------------------------------------------------------------*/
/*
*/
/* Copyright (c) 1995, 2004 IBM Corporation. All rights reserved.
*/
-/* Copyright (c) 2005-2020 Rexx Language Association. All rights reserved.
*/
+/* Copyright (c) 2005-2025 Rexx Language Association. All rights reserved.
*/
/*
*/
/* This program and the accompanying materials are made available under
*/
/* the terms of the Common Public License v1.0 which accompanies this
*/
@@ -191,6 +191,7 @@
KeywordEntry("FORM", BUILTIN_FORM),
KeywordEntry("FORMAT", BUILTIN_FORMAT),
KeywordEntry("FUZZ", BUILTIN_FUZZ),
+ KeywordEntry("GC", BUILTIN_GC),
KeywordEntry("INSERT", BUILTIN_INSERT),
KeywordEntry("LASTPOS", BUILTIN_LASTPOS),
KeywordEntry("LEFT", BUILTIN_LEFT),
@@ -272,6 +273,7 @@
KeywordEntry("FORM", BUILTIN_FORM),
KeywordEntry("FORMAT", BUILTIN_FORMAT),
KeywordEntry("FUZZ", BUILTIN_FUZZ),
+ KeywordEntry("GC", BUILTIN_GC),
KeywordEntry("INSERT", BUILTIN_INSERT),
KeywordEntry("LASTPOS", BUILTIN_LASTPOS),
KeywordEntry("LEFT", BUILTIN_LEFT),
Index: interpreter/parser/Token.hpp
===================================================================
--- interpreter/parser/Token.hpp (revision 13011)
+++ interpreter/parser/Token.hpp (working copy)
@@ -1,7 +1,7 @@
/*----------------------------------------------------------------------------*/
/*
*/
/* Copyright (c) 1995, 2004 IBM Corporation. All rights reserved.
*/
-/* Copyright (c) 2005-2024 Rexx Language Association. All rights reserved.
*/
+/* Copyright (c) 2005-2025 Rexx Language Association. All rights reserved.
*/
/*
*/
/* This program and the accompanying materials are made available under
*/
/* the terms of the Common Public License v1.0 which accompanies this
*/
@@ -508,6 +508,7 @@
BUILTIN_ENDLOCAL,
BUILTIN_SETLOCAL,
BUILTIN_QUALIFY,
+ BUILTIN_GC,
} BuiltinCode;
_______________________________________________
Oorexx-devel mailing list
Oorexx-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/oorexx-devel