Skip to content

Commit

Permalink
docs: hierarchical heaps, heap queries, fix link
Browse files Browse the repository at this point in the history
  • Loading branch information
shwestrick committed Sep 20, 2024
1 parent b64c5d2 commit fbed421
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 1 deletion.
Binary file added docs/assets/heap-query.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
46 changes: 46 additions & 0 deletions docs/runtime-sys/mem-manage/heap-query.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
---
layout: page
title: Heap Queries
parent: Memory Management
---

# Heap Queries

For any [Heap Object](object.html), we can efficiently query which
[Heap](heap.html) contains that object. Typically, this is implemented in
the code as follows: first we get the chunk containing the object, and then we
use the union-find acceleration structure to get to the "level head", i.e., the
representative `HM_HierarchicalHeap` structure for this region of memory.

```c
objptr op; // given a pointer to some object
HM_HierarchicalHeap h; // result is a pointer to a heap
h = HM_getLevelHead(HM_getChunkOf(op));
```

Below is an illustration of a full heap query.
① We start with an `objptr` pointing to some object.
② The function call `HM_getChunkOf(...)` returns the chunk descriptor
(see [Chunks](chunk.html)) for the chunk that contains that object.
③ Next, with the chunk descriptor in hand, we call
`HM_getLevelHead` to traverse the union-find structure.
④ Finally, out of the union-find structure, we arrive at
the appropriate `HM_HierarchicalHeap`.

![Visualizing a heap query]({{site.baseurl}}/assets/heap-query.png){:width="100%"}

{: .note}
> Throughout the run-time system you will also see the following.
> ```c
> h = HM_getLevelHeadPathCompress(HM_getChunkOf(op));
> ```
> This is similar to the approach described above, except that
> it also performs path compression within the union-find structure to help
> accelerate future queries. Some care is needed to avoid concurrency issues,
> because `HM_getLevelHeadPathCompress` modifies the union-find structure.
It might at first seem like heap queries are expensive. In practice, a
typical heap query requires only a bitmask, two pointer dereferences, and a
couple conditionals. Path compression ensures that the number of links
traversed within the union-find structure is
[almost constant](https://en.wikipedia.org/wiki/Disjoint-set_data_structure#History).
27 changes: 27 additions & 0 deletions docs/runtime-sys/mem-manage/heap.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
---
layout: page
title: Hierarchical Heaps
parent: Memory Management
---

# Hierarchical Heaps

One of the key data structures in the MPL runtime system is the
**hierarchical heap**, which we often refer to simply as just a **heap**.
At any moment during execution there will be many heaps. Each heap is a
dynamically resizable memory region that contains [Heap Objects](object.html)
allocated during execution. Heaps do not overlap---every object is contained
within exactly one heap.

Heaps are organized in a tree structure which mirrors the fork-join task
structure of the program. This tree of heaps, called the **heap hierarchy**,
is a dynamic tree which grows and shrinks during execution, as tasks fork and
join.

Heaps are represented by the type [`HM_HierarchicalHeap`](https://github.com/MPLLang/mpl/blob/b64c5d2fb887768a80d010c9de6cc96ec41a4ba6/runtime/gc/hierarchical-heap.h#L50)
in `runtime/gc/hierarchical-heap.h`. A companion type,
[`HM_UnionFindNode`](https://github.com/MPLLang/mpl/blob/b64c5d2fb887768a80d010c9de6cc96ec41a4ba6/runtime/gc/hierarchical-heap.h#L17), is used to accelerate [Heap Queries](heap-query.html)
and also keep track of old `HM_HierarchicalHeap` structs that can be
reclaimed.

TODO...
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ laid out carefully and tagged with GC metadata.
Every object has two components: a payload, and metadata. The payload is where
the actual program data is stored. The metadata records information about the
contents and size of the payload, as well as other info used by the garbage
collector. The metadata usually consists of just a [header](header.md), which is
collector. The metadata usually consists of just a [header](header.html), which is
8 bytes. (Exception: sequence objects have 24 bytes of metadata. See below.)

Pointers to objects always point to the beginning of the payload. These
Expand Down

0 comments on commit fbed421

Please sign in to comment.