Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f260e7ff authored by Shai Barack's avatar Shai Barack
Browse files

Optimize MessageHeap siftUp/Down

When sifting up/down, sift other messages down/up as we traverse, and only store the starting message once at the final position.
Essentially instead of swapping messages at every traversal step, we create an empty bubble where we start and sift the bubble, then store the original message at the final bubble position.

Flag: build.RELEASE_PACKAGE_MESSAGEQUEUE_IMPLEMENTATION
Bug: 421623328
Change-Id: Icb72cc46dbb439423960d01eeb9f786ed446d423
parent 72b6f5ec
Loading
Loading
Loading
Loading
+53 −35
Original line number Diff line number Diff line
@@ -90,55 +90,73 @@ public final class MessageHeap {
        return Message.compareMessages(mHeap[x], mHeap[y]);
    }

    private void swap(int x, int y) {
        Message newX = mHeap[y];
        Message newY = mHeap[x];
        mHeap[x] = newX;
        mHeap[y] = newY;
        newX.heapIndex = x;
        newY.heapIndex = y;
    }

    private void siftDown(int i) {
        int smallest = i;
        int right, left;
        final Message m = mHeap[i];
        final int numElements = mNumElements;
        int half = numElements >>> 1;
        boolean sifted = false;

        while (true) {
            right = rightNodeIdx(i);
            left = leftNodeIdx(i);
        while (i < half) {
            // Find the child to sift down to.
            int childIdx = leftNodeIdx(i);
            Message child = mHeap[childIdx];
            int rightIdx = childIdx + 1;

            if (right < mNumElements && compareMessagesByIdx(right, smallest) < 0) {
                smallest = right;
            if (rightIdx < numElements) {
                final Message right = mHeap[rightIdx];
                if (Message.compareMessages(right, child) < 0) {
                    childIdx = rightIdx;
                    child = right;
                }
            }

            if (left < mNumElements && compareMessagesByIdx(left, smallest) < 0) {
                smallest = left;
            if (Message.compareMessages(m, child) <= 0) {
                // We've found a child that is less than or equal to our message, so we can't
                // traverse down.
                break;
            }

            if (smallest != i) {
                swap(i, smallest);
                i = smallest;
                continue;
            // Sift the child up and continue traversing down.
            mHeap[i] = child;
            child.heapIndex = i;
            i = childIdx;
            sifted = true;
        }
            break;

        // We've arrived at the final position. Store our message, if it moved.
        if (sifted) {
            mHeap[i] = m;
            m.heapIndex = i;
        }
    }

    private boolean siftUp(int i) {
        boolean swapped = false;
        /*
         * We never pass null to compareMessages here, mHeap[i] is known to be occupied as is
         * its parent node
         */
        while (i != 0 && Message.compareMessages(mHeap[i], getParentNode(i)) < 0) {
        final Message m = mHeap[i];
        boolean sifted = false;

        // While we're not at the top of the heap, we can try to sift up.
        while (i > 0) {
            int p = parentNodeIdx(i);
            Message parent = mHeap[p];
            if (Message.compareMessages(parent, m) < 0) {
                // We've found a parent that is less than our message, so we can't sift up.
                break;
            }

            swap(i, p);
            swapped = true;
            // Sift the parent down and continue traversing up.
            mHeap[i] = parent;
            parent.heapIndex = i;
            i = p;
            sifted = true;
        }

        // We've arrived at the final position. Store our message, if it moved.
        if (sifted) {
            mHeap[i] = m;
            m.heapIndex = i;
        }

        return swapped;
        return sifted;
    }

    private void maybeGrow() {