Skip to content

Commit

Permalink
xfs: improve buffer cache hash scalability
Browse files Browse the repository at this point in the history
When doing large parallel file creates on a 16p machines, large amounts of
time is being spent in _xfs_buf_find(). A system wide profile with perf top
shows this:

          1134740.00 19.3% _xfs_buf_find
           733142.00 12.5% __ticket_spin_lock

The problem is that the hash contains 45,000 buffers, and the hash table width
is only 256 buffers. That means we've got around 200 buffers per chain, and
searching it is quite expensive. The hash table size needs to increase.

Secondly, every time we do a lookup, we promote the buffer we find to the head
of the hash chain. This is causing cachelines to be dirtied and causes
invalidation of cachelines across all CPUs that may have walked the hash chain
recently. hence every walk of the hash chain is effectively a cold cache walk.
Remove the promotion to avoid this invalidation.

The results are:

          1045043.00 21.2% __ticket_spin_lock
           326184.00  6.6% _xfs_buf_find

A 70% drop in the CPU usage when looking up buffers. Unfortunately that does
not result in an increase in performance underthis workload as contention on
the inode_lock soaks up most of the reduction in CPU usage.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
  • Loading branch information
Dave Chinner committed Sep 2, 2010
1 parent 2bfc96a commit 9bc08a4
Show file tree
Hide file tree
Showing 2 changed files with 1 addition and 8 deletions.
8 changes: 1 addition & 7 deletions fs/xfs/linux-2.6/xfs_buf.c
Original file line number Diff line number Diff line change
Expand Up @@ -440,12 +440,7 @@ _xfs_buf_find(
ASSERT(btp == bp->b_target);
if (bp->b_file_offset == range_base &&
bp->b_buffer_length == range_length) {
/*
* If we look at something, bring it to the
* front of the list for next time.
*/
atomic_inc(&bp->b_hold);
list_move(&bp->b_hash_list, &hash->bh_list);
goto found;
}
}
Expand Down Expand Up @@ -1443,8 +1438,7 @@ xfs_alloc_bufhash(
{
unsigned int i;

btp->bt_hashshift = external ? 3 : 8; /* 8 or 256 buckets */
btp->bt_hashmask = (1 << btp->bt_hashshift) - 1;
btp->bt_hashshift = external ? 3 : 12; /* 8 or 4096 buckets */
btp->bt_hash = kmem_zalloc_large((1 << btp->bt_hashshift) *
sizeof(xfs_bufhash_t));
for (i = 0; i < (1 << btp->bt_hashshift); i++) {
Expand Down
1 change: 0 additions & 1 deletion fs/xfs/linux-2.6/xfs_buf.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,6 @@ typedef struct xfs_buftarg {
size_t bt_smask;

/* per device buffer hash table */
uint bt_hashmask;
uint bt_hashshift;
xfs_bufhash_t *bt_hash;

Expand Down

0 comments on commit 9bc08a4

Please sign in to comment.