Is there any kind of garbage collector?
Some languages have the concept of a garbage collector for automatic memory management. I'd like to know if something like this exists in InterSystems Caché in the context of routines, %CSP.REST, or %CSP.Page.
The question arises from the %Close() method of the %RegisteredObject class. This indicates that I need to manually clear the object from memory if it's no longer in use, or in the web context, if the request has completed. Is this correct? Or am I completely wrong?
Thank you!
Comments
InterSystems IRIS employs a memory management approach related to object references (OREFs) rather than a traditional garbage collector mechanism. Here's how it works:
Automatic Memory Management for Object References:
- When an object is created, InterSystems IRIS keeps a reference count to track how many variables are pointing to the object. This count is incremented when a reference is made to the object and decremented when the reference is removed (e.g., the variable goes out of scope, is explicitly killed, or assigned a new value).
- If the reference count reaches zero, the in-memory object is automatically destroyed and its
%OnClose()method (if defined) is executed. This is a form of automatic cleanup tied to the object’s lifecycle and reference count [1].
Manual Management of Object References:
- Although
%Close()exists in some older object classes, it is deprecated and does not actually remove object references. To remove an object reference, you should assign an empty string ("") to it, or use theKILLcommand to remove the variable holding the reference. When there are no remaining references to the object, it is removed from memory [2][1].
- Although
Special Functions for Object Lifecycle Checks:
- The
$ISOBJECT(expr)function can check whether a given variable holds a valid object reference, returning 1 for valid references and -1 for invalid ones. This is useful to determine if an object still exists or needs cleanup [2].
- The
This overall mechanism ensures efficient memory management of objects and avoids memory leaks, as objects are destroyed once no references point to them. While this approach achieves similar results to garbage collection, it is not automatic in the same sense and requires developers to account for object scope and references properly.
Sources:
Although the %Close method doesn't do anything, there is a useful %OnClose callback, where you can do some cleanup if needed, such killing a temporary global.
The is a core process called GARCOL which is used to handle large global kills.
Securing Caché, Ensemble, And Operating System Resources | Caché & Ensemble 2018.1.0-2018.1.3
%Close is called automatically. Consider the following example:
Class Utils.GC Extends%RegisteredObject
{
Property Type As%String;/// do ##class(Utils.GC).Test()ClassMethod Test()
{
set obj = ..%New("explicit")
kill obj
do..Implicit()
}
ClassMethod Implicit()
{
set obj = ..%New("implicit")
// obj will be removed from memory after we exit current method/frame.
}
Method %OnClose() As%Status [ Private, ServerOnly = 1 ]
{
Write"%Close is running: ", ..Type,!
Quit$$$OK
}
Method %OnNew(type) As%Status [ Private, ServerOnly = 1 ]
{
Set..Type = type
Quit$$$OK
}
}Here's the output from the Test method:
HCC>do##class(Utils.GC).Test()
%Close is running: explicit
%Close is running: implicitThank you! Another question that arose with this example is whether it's possible to apply a singleton pattern? Well, I understand that the discard was instantaneous.
Check this discussion. % variables are the simplest singletons there is.
Very good!
💡 This question is considered a Key Question. More details here.