• G
    lib/sort: use more efficient bottom-up heapsort variant · 22a241cc
    George Spelvin 提交于
    This uses fewer comparisons than the previous code (approaching half as
    many for large random inputs), but produces identical results; it
    actually performs the exact same series of swap operations.
    
    Specifically, it reduces the average number of compares from
      2*n*log2(n) - 3*n + o(n)
    to
        n*log2(n) + 0.37*n + o(n).
    
    This is still 1.63*n worse than glibc qsort() which manages n*log2(n) -
    1.26*n, but at least the leading coefficient is correct.
    
    Standard heapsort, when sifting down, performs two comparisons per
    level: one to find the greater child, and a second to see if the current
    node should be exchanged with that child.
    
    Bottom-up heapsort observes that it's better to postpone the second
    comparison and search for the leaf where -infinity would be sent to,
    then search back *up* for the current node's destination.
    
    Since sifting down usually proceeds to the leaf level (that's where half
    the nodes are), this does O(1) second comparisons rather than log2(n).
    That saves a lot of (expensive since Spectre) indirect function calls.
    
    The one time it's worse than the previous code is if there are large
    numbers of duplicate keys, when the top-down algorithm is O(n) and
    bottom-up is O(n log n).  For distinct keys, it's provably always
    better, doing 1.5*n*log2(n) + O(n) in the worst case.
    
    (The code is not significantly more complex.  This patch also merges the
    heap-building and -extracting sift-down loops, resulting in a net code
    size savings.)
    
    x86-64 code size 885 -> 767 bytes (-118)
    
    (I see the checkpatch complaint about "else if (n -= size)".  The
    alternative is significantly uglier.)
    
    Link: http://lkml.kernel.org/r/2de8348635a1a421a72620677898c7fd5bd4b19d.1552704200.git.lkml@sdf.orgSigned-off-by: NGeorge Spelvin <lkml@sdf.org>
    Acked-by: NAndrey Abramov <st5pub@yandex.ru>
    Acked-by: NRasmus Villemoes <linux@rasmusvillemoes.dk>
    Reviewed-by: NAndy Shevchenko <andriy.shevchenko@linux.intel.com>
    Cc: Daniel Wagner <daniel.wagner@siemens.com>
    Cc: Dave Chinner <dchinner@redhat.com>
    Cc: Don Mullis <don.mullis@gmail.com>
    Cc: Geert Uytterhoeven <geert@linux-m68k.org>
    Signed-off-by: NAndrew Morton <akpm@linux-foundation.org>
    Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
    22a241cc
sort.c 7.2 KB