Here's a little implementation info:

'Garbage collection' in one sense means collecting contiguous free blocks into one large free block. This is performed only at the end of executing a named entity. The memory allocator makes a check whenever a block is freed, to see if garbage collection should be executed at the end of the next named verb.

What gc3() is doing is freeing the blocks that are no longer active. Every time a block is allocated its death warrant is filled out & put onto the 'tpush stack'. When the routine that allocated the block exits, every block that the routine allocated is freed (actually, its usecount is decremented so that if it has been assigned, it won't be freed while the assignment is active). gc3() is used by primitives that call for lots of work by other primitives: such a primitive must check from time to time to clear the tpush stack lest too much accumulate. Since the primitive isn't actually finished, there may be some blocks it has allocated that shouldn't be freed: these are the arguments to gc3(). gc3() raises their usecounts to protect them, processes the tpush stack, and then puts the protected arguments back onto the tpush stack so that they will be freed when the routine ends.

So there are lots of possible responses to this problem:
 * gc3() less often
* use some other criterion, like amount of memory activity, to trigger the call to gc3() * Make the ra() calls in gc3(), which are expensive for boxed arguments, run faster
 * implement gc3() in a way that obviates the need for ra()

Henry Rich

On 1/12/2017 4:25 PM, Raul Miller wrote:
I think issues might be (a) we don't know how much memory is being
allocated in each iteration, and (b) memory allocation time might be
an awkward spot for a garbage collect.

That said, logically speaking, we want to reclaim memory when we have
a lot of unused space. And that tends to mean after a lot has been
allocated.

So, anyways, it should be the case that we're tracking how much memory
has been added and we attempt to reclaim after we've added a lot.

(There's a potential exception here when we're right at the threshold,
but that issue will tend to cause performance to take a dive, and it
can become really difficult to interrupt J at that point - I'm not
sure there's any good approach for that situation. Probably worth
neglecting initially but eventually we'll have to deal with resource
thresholds. On a related note, the current jbrk implementation tends
to lead first to states where you have to reboot the machine to regain
control and then after that to being reluctant to experiment with J.
Personally, I'd prefer if jqt had jbrk functionality built it (with
the dreaded 'are you sure'). But this tangent is getting way too far
off topic now...)

Anyways, there's no perfect solutions but maybe we can do better.

Thanks,


----------------------------------------------------------------------
For information about J forums see http://www.jsoftware.com/forums.htm

Reply via email to