3

I have an AVL tree and I need to traverse it in ascending and descending order. I implemented a simple algorithm, where knowing the tree size in advance, I allocate an array and assign 0 to a counter, then I traverse the tree as follows:

void traverseAscending(Node cur) {
    if(cur.left != null) traverseAscending(cur.left);
    outVals[totOuts] = cur.data;
    totOuts++;
    if(cur.right != null) traverseAscending(cur.right);
}

This is the classics we've all been taught. However, it's slow likely because the branches are mispredicted all the time.

How to traverse the tree in a way friendly for branch predictor?

UPDATE: answering the comments,

  1. I came to the conclusion that it's branching that is slow because I profiled the application.
  2. The cache should not be an issue because I have multiple relatively small trees that fit the cache.
  3. Indeed, the share of this method in the profiler decreases over time, but I would think it's because the algorithm changes so the bottlenecks change. The first ~10 minutes of running this method takes ~6% of the runtime.
Serge Rogatch
  • 13,865
  • 7
  • 86
  • 158
  • Is it copying the node on every function invocation? Have you tried passing it by reference? Also, where are the array and the counter actually stored, this doesn't look like a nested function? – Andrey Tyukin Oct 24 '22 at 10:04
  • @AndreyTyukin, it's Java, so everything is passed by reference. The array and the counter are stored in the object accessed via `this` reference. – Serge Rogatch Oct 24 '22 at 10:15
  • 1
    Can you rearrange your tree beforehand? If not, I don't think there's a general solution, since the depths of two consecutive leaves can always differ by one of three values (-1, 0, or 1). – Nelfeal Oct 24 '22 at 10:24
  • 2
    How did you come to the conclusion that branch prediction is to blame - did you profile it? – 500 - Internal Server Error Oct 24 '22 at 11:18
  • 1
    This code isn't slow, but an iterative version could be a bit faster. Either way, the time is probably dominated by memory access to the node objects. Most likely you measured it before the JIT compiler could finish optimizing it. – Matt Timmermans Oct 24 '22 at 12:46
  • @MattTimmermans and "Internal Server Error", I've addressed your questions in an update to the post. – Serge Rogatch Oct 24 '22 at 15:26
  • Every branch is travelled once (recursive call) and a second time (returning from recursion). It is impossible to do the traversal without visiting all edges... This is O(n). – trincot Oct 24 '22 at 19:32

0 Answers0