• David Rowley's avatar
    Optimize compactify_tuples function · 19c60ad6
    David Rowley authored
    This function could often be seen in profiles of vacuum and could often
    be a significant bottleneck during recovery. The problem was that a qsort
    was performed in order to sort an array of item pointers in reverse offset
    order so that we could use that to safely move tuples up to the end of the
    page without overwriting the memory of yet-to-be-moved tuples. i.e. we
    used to compact the page starting at the back of the page and move towards
    the front. The qsort that this required could be expensive for pages with
    a large number of tuples.
    
    In this commit, we take another approach to tuple compactification.
    
    Now, instead of sorting the remaining item pointers array we first check
    if the array is presorted and only memmove() the tuples that need to be
    moved. This presorted check can be done very cheaply in the calling
    functions when the array is being populated. This presorted case is very
    fast.
    
    When the item pointer array is not presorted we must copy tuples that need
    to be moved into a temp buffer before copying them back into the page
    again. This differs from what we used to do here as we're now copying the
    tuples back into the page in reverse line pointer order. Previously we
    left the existing order alone.  Reordering the tuples results in an
    increased likelihood of hitting the pre-sorted case the next time around.
    Any newly added tuple which consumes a new line pointer will also maintain
    the correct sort order of tuples in the page which will also result in the
    presorted case being hit the next time.  Only consuming an unused line
    pointer can cause the order of tuples to go out again, but that will be
    corrected next time the function is called for the page.
    
    Benchmarks have shown that the non-presorted case is at least equally as
    fast as the original qsort method even when the page just has a few
    tuples. As the number of tuples becomes larger the new method maintains
    its performance whereas the original qsort method became much slower when
    the number of tuples on the page became large.
    
    Author: David Rowley
    Reviewed-by: Thomas Munro
    Tested-by: Jakub Wartak
    Discussion: https://postgr.es/m/CA+hUKGKMQFVpjr106gRhwk6R-nXv0qOcTreZuQzxgpHESAL6dw@mail.gmail.com
    19c60ad6
bufpage.c 39.7 KB