chapel-lang / chapel

a Productive Parallel Programming Language
https://chapel-lang.org
Other
1.76k stars 414 forks source link

Feature Request: Arena/Region allocation for better lifetime management #10820

Open LouisJenkinsCS opened 5 years ago

LouisJenkinsCS commented 5 years ago

This addresses the issue presented in #10819. In Rust, there is the arena, which is a zone of memory that the user can request where all allocations are tied to that particular instance of the arena, and where all objects allocated from the arena are cleaned up when the arena goes out of scope. The arena can be implemented as a Chapel module where it is a fixed-sized buffer of objects, essentially a contiguous memory pool.

One variant and research-idea is to make use of my RCUArray abstraction and 'dynamic heap' idea to make it a dynamically-expanding and distributed arena! @mppf

LouisJenkinsCS commented 5 years ago

One alternative implementation would be to give an arena implicitly to each class that it can allocate managed data types from. Although giving the user more control is always a good thing in my opinion, but #10821 gives a more automated compiler-driven approach to this problem.

mppf commented 5 years ago

This is interesting but it doesn't necessarily solve the problem because we need to call deinit methods on user class instances allocated in the arena. So something like TypedArena - that can only store objects of one type - might be necessary to address your concern.

LouisJenkinsCS commented 5 years ago

This is interesting but it doesn't necessarily solve the problem because we need to call deinit methods on user class instances allocated in the arena.

True, it does need to invoke deinit on each class instance, but there won't be any recursive deinitializers causing stack-overflow. For example, take the tree example...

class Node {
    type eltType;
    var left : borrowed Node(eltType);
    var right : borrowed Node(eltType);
}
class Tree {
    type eltType;
    var root : borrowed Node(eltType);
    var arena = new owned Arena(Node(eltType));
}

proc Tree.insert(elt : eltType) {
    var node = arena.allocate(elt);
    // ...Insertion logic...    
}

var tree = new Tree();
for i in 1..10 do tree.insert(i);

In this case, the arena owns the actual Node(eltType) rather than the actual Tree. That does solve the problem in that left and right are borrowed and do not result in recursion during deinitialization. Let me know if I missed something.

LouisJenkinsCS commented 5 years ago

Accidentally hit close and comment on mobile