• Liu Bo's avatar
    Btrfs: delayed-refs: use rb_first_cached for href_root · 5c9d028b
    Liu Bo authored
    rb_first_cached() trades an extra pointer "leftmost" for doing the same
    job as rb_first() but in O(1).
    
    Functions manipulating href_root need to get the first entry, this
    converts href_root to use rb_first_cached().
    
    This patch is first in the sequenct of similar updates to other rbtrees
    and this is analysis of the expected behaviour and improvements.
    
    There's a common pattern:
    
    while (node = rb_first) {
            entry = rb_entry(node)
            next = rb_next(node)
            rb_erase(node)
            cleanup(entry)
    }
    
    rb_first needs to traverse the tree up to logN depth, rb_erase can
    completely reshuffle the tree. With the caching we'll skip the traversal
    in rb_first.  That's a cached memory access vs looped pointer
    dereference trade-off that IMHO has a clear winner.
    
    Measurements show there's not much difference in a sample tree with
    10000 nodes: 4.5s / rb_first and 4.8s / rb_first_cached. Real effects of
    caching and pointer chasing are unpredictable though.
    
    Further optimzations can be done to avoid the expensive rb_erase step.
    In some cases it's ok to process the nodes in any order, so the tree can
    be traversed in post-order, not rebalancing the children nodes and just
    calling free. Care must be taken regarding the next node.
    Tested-by: default avatarHolger Hoffstätte <holger@applied-asynchrony.com>
    Signed-off-by: default avatarLiu Bo <bo.liu@linux.alibaba.com>
    Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
    [ update changelog from mail discussions ]
    Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
    5c9d028b
extent-tree.c 300 KB