[ready for review] btreeg: add support for no alloc iter#52
[ready for review] btreeg: add support for no alloc iter#52tidwall merged 8 commits intotidwall:masterfrom
Conversation
|
Is the goal here to have a zero alloc iterator? |
This is the only alloc which is significant enough to show up in our profiles. I'm just using a seek + next. |
|
Can you provide a little more info about what you are seeing? |
|
It just occurred to me, but if you are only using Seek and Next, you may want to consider using the Ascend function. It has a much lower footprint, doesn't touch the heap, and is generally faster than using the Iter functions. |
|
I can't use ascend as I need to do a specific kind of iteration. Let's say the keys are k1 < k2 < k3 < k4. If I have have a pivot key k_x such that k_2 < k_x < k_3, then I need my ascension to start from k_2 and not k_3. Ascend would start the iteration at k_3. Right now, we use Descend + Ascend combo for this, but that's too expensive. First descend to find the first key <= k_x, and then Ascend using k_x as pivot. I don't want to use an iterator either, I'd rather just use a function like ascend which starts iteration one key prior the first key which is >=. Basically what I want is Descend + scan forward which does a single seek to find the item to start the scan at(k_2 in the above example), and the scans forward like ascend. I can implement this if you're open to it. What do you think? |
|
So perhaps functions similar to Ascend and Descend, that starts at a pivot, but allows for moving forward and backwards like cursor? That's interesting actually. I'm seeing something like: (not sure of the name yet) const (
Stop Action = iota
Prev
Next
)
func (tr *BTree[T]) IterAscend(pivot T, iter(item T) Action)
func (tr *BTree[T]) IterDescend(pivot T, iter(item T) Action)
func (tr *BTree[T]) IterScan(iter(item T) Action)
func (tr *BTree[T]) IterReverse(iter(item T) Action)These could work like Ascend, Descend, Scan, and Reverse, but instead or returning true or false, you can return Stop, Next, or Prev. This will allow to start at any pivot and change direction on the fly. |
|
@tidwall Sorry about the delay. I've made a lot of changes to this pr, it's a lot different from what we were discussing. I've included a benchmark which shows the allocation with the regular iterators. Then, I've introduced a new api to use the iterator without any allocations. Please take a look whenever you get the chance. The changes and the reasoning is described here: #52 (comment) I like the idea you mentioned here: #52 (comment), I've never seen an API like that before and it's pretty interesting, but just using the existing iterator is sufficient for our use case. |
|
Overall LGTM. Though I am wondering if we can simply replace the existing |
|
@tidwall Please take a look. Re-using Release, and made the re-use of the iterator safer by zeroing out memory. |
|
Looks good! |
This pr introduces the following API:
First, an iterator is created using the BtreeG.Iter or IterMut method. Then, the iterator can be re-used by first calling
ReleaseReusable, and then callingInit.This prevents two types of allocations: