• Filipe Manana's avatar
    btrfs: add btree read ahead for full send operations · 19358b15
    Filipe Manana authored
    When doing a full send we know that we are going to be reading every node
    and leaf of the send root, so we benefit from enabling read ahead for the
    btree.
    
    This change enables read ahead for full send operations only, incremental
    sends will have read ahead enabled in a different way by a separate patch.
    
    The following test script was used to measure the improvement on a box
    using an average, consumer grade, spinning disk and with 16GiB of RAM:
    
      $ cat test.sh
      #!/bin/bash
    
      DEV=/dev/sdj
      MNT=/mnt/sdj
      MKFS_OPTIONS="--nodesize 16384"     # default, just to be explicit
      MOUNT_OPTIONS="-o max_inline=2048"  # default, just to be explicit
    
      mkfs.btrfs -f $MKFS_OPTIONS $DEV > /dev/null
      mount $MOUNT_OPTIONS $DEV $MNT
    
      # Create files with inline data to make it easier and faster to create
      # large btrees.
      add_files()
      {
          local total=$1
          local start_offset=$2
          local number_jobs=$3
          local total_per_job=$(($total / $number_jobs))
    
          echo "Creating $total new files using $number_jobs jobs"
          for ((n = 0; n < $number_jobs; n++)); do
              (
                  local start_num=$(($start_offset + $n * $total_per_job))
                  for ((i = 1; i <= $total_per_job; i++)); do
                      local file_num=$((start_num + $i))
                      local file_path="$MNT/file_${file_num}"
                      xfs_io -f -c "pwrite -S 0xab 0 2000" $file_path > /dev/null
                      if [ $? -ne 0 ]; then
                          echo "Failed creating file $file_path"
                          break
                      fi
                  done
              ) &
              worker_pids[$n]=$!
          done
    
          wait ${worker_pids[@]}
    
          sync
          echo
          echo "btree node/leaf count: $(btrfs inspect-internal dump-tree -t 5 $DEV | egrep '^(node|leaf) ' | wc -l)"
      }
    
      initial_file_count=500000
      add_files $initial_file_count 0 4
    
      echo
      echo "Creating first snapshot..."
      btrfs subvolume snapshot -r $MNT $MNT/snap1
    
      echo
      echo "Adding more files..."
      add_files $((initial_file_count / 4)) $initial_file_count 4
    
      echo
      echo "Updating 1/50th of the initial files..."
      for ((i = 1; i < $initial_file_count; i += 50)); do
          xfs_io -c "pwrite -S 0xcd 0 20" $MNT/file_$i > /dev/null
      done
    
      echo
      echo "Creating second snapshot..."
      btrfs subvolume snapshot -r $MNT $MNT/snap2
    
      umount $MNT
    
      echo 3 > /proc/sys/vm/drop_caches
      blockdev --flushbufs $DEV &> /dev/null
      hdparm -F $DEV &> /dev/null
    
      mount $MOUNT_OPTIONS $DEV $MNT
    
      echo
      echo "Testing full send..."
      start=$(date +%s)
      btrfs send $MNT/snap1 > /dev/null
      end=$(date +%s)
      echo
      echo "Full send took $((end - start)) seconds"
    
      umount $MNT
    
      echo 3 > /proc/sys/vm/drop_caches
      blockdev --flushbufs $DEV &> /dev/null
      hdparm -F $DEV &> /dev/null
    
      mount $MOUNT_OPTIONS $DEV $MNT
    
      echo
      echo "Testing incremental send..."
      start=$(date +%s)
      btrfs send -p $MNT/snap1 $MNT/snap2 > /dev/null
      end=$(date +%s)
      echo
      echo "Incremental send took $((end - start)) seconds"
    
      umount $MNT
    
    Before this change, full send duration:
    
      with $initial_file_count == 200000:  165 seconds
      with $initial_file_count == 500000:  407 seconds
    
    After this change, full send duration:
    
      with $initial_file_count == 200000:  149 seconds (-10.2%)
      with $initial_file_count == 500000:  353 seconds (-14.2%)
    
    For $initial_file_count == 200000 there are 62600 nodes and leaves in the
    btree of the first snapshot, while for $initial_file_count == 500000 there
    are 152476 nodes and leaves. The roots were at level 2.
    Signed-off-by: default avatarFilipe Manana <fdmanana@suse.com>
    Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
    Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
    19358b15
send.c 181 KB