Optimize sifting down in binaryheap.
authorNathan Bossart <[email protected]>
Wed, 30 Oct 2024 16:28:34 +0000 (11:28 -0500)
committerNathan Bossart <[email protected]>
Wed, 30 Oct 2024 16:28:34 +0000 (11:28 -0500)
Presently, each iteration of the loop in sift_down() will perform
3 comparisons if both children are larger than the parent node (2
for comparing each child to the parent node, and a third to compare
the children to each other).  By first comparing the children to
each other and then comparing the larger child to the parent node,
we can accomplish the same thing with just 2 comparisons (while
also not affecting the number of comparisons in any other case).

Author: ChangAo Chen
Reviewed-by: Robert Haas
Discussion: https://postgr.es/m/tencent_0142D8DA90940B9930BCC08348BBD6D0BB07%40qq.com

src/common/binaryheap.c

index 7377ebdf1568153e6a404c7fd336092c7f0b294b..159a316c221ac6d3566c00032e293b3eb7281574 100644 (file)
@@ -323,34 +323,23 @@ sift_down(binaryheap *heap, int node_off)
    {
        int         left_off = left_offset(node_off);
        int         right_off = right_offset(node_off);
-       int         swap_off = 0;
+       int         swap_off = left_off;
 
-       /* Is the left child larger than the parent? */
-       if (left_off < heap->bh_size &&
-           heap->bh_compare(node_val,
-                            heap->bh_nodes[left_off],
-                            heap->bh_arg) < 0)
-           swap_off = left_off;
-
-       /* Is the right child larger than the parent? */
+       /* Is the right child larger than the left child? */
        if (right_off < heap->bh_size &&
-           heap->bh_compare(node_val,
+           heap->bh_compare(heap->bh_nodes[left_off],
                             heap->bh_nodes[right_off],
                             heap->bh_arg) < 0)
-       {
-           /* swap with the larger child */
-           if (!swap_off ||
-               heap->bh_compare(heap->bh_nodes[left_off],
-                                heap->bh_nodes[right_off],
-                                heap->bh_arg) < 0)
-               swap_off = right_off;
-       }
+           swap_off = right_off;
 
        /*
-        * If we didn't find anything to swap, the heap condition is
+        * If no children or parent is >= the larger child, heap condition is
         * satisfied, and we're done.
         */
-       if (!swap_off)
+       if (left_off >= heap->bh_size ||
+           heap->bh_compare(node_val,
+                            heap->bh_nodes[swap_off],
+                            heap->bh_arg) >= 0)
            break;
 
        /*