• Filipe Manana's avatar
    btrfs: loop only once over data sizes array when inserting an item batch · b7ef5f3a
    Filipe Manana authored
    When inserting a batch of items into a btree, we end up looping over the
    data sizes array 3 times:
    
    1) Once in the caller of btrfs_insert_empty_items(), when it populates the
       array with the data sizes for each item;
    
    2) Once at btrfs_insert_empty_items() to sum the elements of the data
       sizes array and compute the total data size;
    
    3) And then once again at setup_items_for_insert(), where we do exactly
       the same as what we do at btrfs_insert_empty_items(), to compute the
       total data size.
    
    That is not bad for small arrays, but when the arrays have hundreds of
    elements, the time spent on looping is not negligible. For example when
    doing batch inserts of delayed items for dir index items or when logging
    a directory, it's common to have 200 to 260 dir index items in a single
    batch when using a leaf size of 16K and using file names between 8 and 12
    characters. For a 64K leaf size, multiply that by 4. Taking into account
    that during directory logging or when flushing delayed dir index items we
    can have many of those large batches, the time spent on the looping adds
    up quickly.
    
    It's also more important to avoid it at setup_items_for_insert(), since
    we are holding a write lock on a leaf and, in some cases, on upper nodes
    of the btree, which causes us to block other tasks that want to access
    the leaf and nodes for longer than necessary.
    
    So change the code so that setup_items_for_insert() and
    btrfs_insert_empty_items() no longer compute the total data size, and
    instead rely on the caller to supply it. This makes us loop over the
    array only once, where we can both populate the data size array and
    compute the total data size, taking advantage of spatial and temporal
    locality. To make this more manageable, use a structure to contain
    all the relevant details for a batch of items (keys array, data sizes
    array, total data size, number of items), and use it as an argument
    for btrfs_insert_empty_items() and setup_items_for_insert().
    
    This patch is part of a small patchset that is comprised of the following
    patches:
    
      btrfs: loop only once over data sizes array when inserting an item batch
      btrfs: unexport setup_items_for_insert()
      btrfs: use single bulk copy operations when logging directories
    
    This is patch 1/3 and performance results, and the specific tests, are
    included in the changelog of patch 3/3.
    Signed-off-by: default avatarFilipe Manana <fdmanana@suse.com>
    Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
    b7ef5f3a
inode.c 308 KB