xfs: speed up directory bestfree block scanning
authorDave Chinner <dchinner@redhat.com>
Thu, 29 Aug 2019 16:04:07 +0000 (09:04 -0700)
committerDarrick J. Wong <darrick.wong@oracle.com>
Sat, 31 Aug 2019 05:43:57 +0000 (22:43 -0700)
commit610125ab1e4b1b48dcffe74d9d82b0606bf1b923
tree37122bf616dc4405830e16529859e4a4961b758c
parent0e822255f95db400e56e19773e04755d79b50bda
xfs: speed up directory bestfree block scanning

When running a "create millions inodes in a directory" test
recently, I noticed we were spending a huge amount of time
converting freespace block headers from disk format to in-memory
format:

 31.47%  [kernel]  [k] xfs_dir2_node_addname
 17.86%  [kernel]  [k] xfs_dir3_free_hdr_from_disk
  3.55%  [kernel]  [k] xfs_dir3_free_bests_p

We shouldn't be hitting the best free block scanning code so hard
when doing sequential directory creates, and it turns out there's
a highly suboptimal loop searching the the best free array in
the freespace block - it decodes the block header before checking
each entry inside a loop, instead of decoding the header once before
running the entry search loop.

This makes a massive difference to create rates. Profile now looks
like this:

  13.15%  [kernel]  [k] xfs_dir2_node_addname
   3.52%  [kernel]  [k] xfs_dir3_leaf_check_int
   3.11%  [kernel]  [k] xfs_log_commit_cil

And the wall time/average file create rate differences are
just as stark:

create time(sec) / rate (files/s)
File count      vanilla     patched
  10k    0.41 / 24.3k    0.42 / 23.8k
  20k    0.74 / 27.0k    0.76 / 26.3k
 100k    3.81 / 26.4k    3.47 / 28.8k
 200k    8.58 / 23.3k    7.19 / 27.8k
   1M   85.69 / 11.7k   48.53 / 20.6k
   2M  280.31 /  7.1k  130.14 / 15.3k

The larger the directory, the bigger the performance improvement.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
fs/xfs/libxfs/xfs_dir2_node.c