Ubuntu – How to improve the server disk performance

diskperformanceraidserver

I have an HP Microserver running Ubuntu 10.04 LTS. It's a low power server with 5 internal drive bays. I use it to backup my remote servers, VPSs and local laptops over the network. I want to get the best performance from the disks, but I don't know if it's setup optimally, so I'm looking for some advice.

My server runs rsnapshot multiple times a day to backup remote hosts. The actual incremental backup part takes very little time. The significant time is spent doing things like:-

/bin/cp -al /srv/rsnapshot/hourly.0 /srv/rsnapshot/hourly.1

Which takes about 2 hours. I realise there are a bazillion tiny files in there.

$ sudo du -hs hourly.1
659G    hourly.1

Also when rsnapshot deletes an old backup this can take a long time:-

/bin/rm -rf /srv/rsnapshot/daily.6/

Which takes about half an hour.

My questions are as follows, configuration of server and some IO stats are detailed below. I can of course provide more debug info if necessary:-

How can I identify where the bottlenecks are?

Am I reaching the limits of what's capable (IO wise) with this box?

Are there any performance tweaks I could make?

Should I use a different RAID level?

Would it make sense to swap two of the internal RAID disks (half of each mirror) with two 'other halves of the other mirror' on the external array?

Note: I'm somewhat not inclined to be doing things like compiling my own kernel. Ideally I'd like to stick on 10.04 LTS, unless there's some magic in later versions that makes this all work a lot quicker.

Internally the server has 1x160GB SATA boot disk and 4x2TB disks:-

Disk /dev/sde: 160.0 GB, 160041885696 bytes
Disk /dev/sdf: 2000.4 GB, 2000398934016 bytes
Disk /dev/sdh: 2000.4 GB, 2000398934016 bytes
Disk /dev/sdi: 2000.4 GB, 2000398934016 bytes
Disk /dev/sdg: 2000.4 GB, 2000398934016 bytes

The four internal 2TB disks are in a software MD RAID10 setup:-

md0 : active raid10 sdg1[3] sdh1[0] sdi1[2] sdf1[1]
      3907023872 blocks 64K chunks 2 near-copies [4/4] [UUUU]

Additionally I have an external EDGE10 drive enclosure which is connected via a PCI-E eSATA card and contains four more drives of 500GB:-

Disk /dev/sda: 500.1 GB, 500107862016 bytes
Disk /dev/sdb: 500.1 GB, 500107862016 bytes
Disk /dev/sdc: 500.1 GB, 500107862016 bytes
Disk /dev/sdd: 500.1 GB, 500107862016 bytes

This is also setup as an MD RAID10 array

md1 : active raid10 sdb1[1] sda1[0] sdd1[3] sdc1[2]
      976767872 blocks 64K chunks 2 near-copies [4/4] [UUUU]

md0 and md1 are combined to make one big LVM. Note: I only recently added the external array, so it's pretty much blank, I don't think there are any blocks on it right now.

This is presented as an LVM volume:-

--- Logical volume ---
LV Name                /dev/data/data
VG Name                data
LV UUID                amZCgU-sQLi-R363-dUFx-Bcdf-iwlt-ZNnDp8
LV Write Access        read/write
LV Status              available
# open                 1
LV Size                4.54 TiB
Current LE             1190134
Segments               2
Allocation             inherit
Read ahead sectors     auto
- currently set to     512
Block device           251:0

Which is formatted as EXT4 and mounted as /srv:-

/dev/mapper/data-data on /srv type ext4 (rw)

There's plenty of free space.

/dev/mapper/data-data
                      4.5T  2.2T  2.1T  51% /srv

Other information that might be useful:-

$ uname -a
Linux ubuntuserver 2.6.32-32-server #62-Ubuntu SMP Wed Apr 20 22:07:43 UTC 2011 x86_64 GNU/Linux

.

00:11.0 SATA controller: ATI Technologies Inc SB700/SB800 SATA Controller [AHCI mode] (rev 40)
02:00.0 RAID bus controller: Silicon Image, Inc. SiI 3132 Serial ATA Raid II Controller (rev 01)

When doing the cp command during rsnapshot I see the following in iostat:-

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           0.55    0.00    5.47   66.14    0.00   27.85

Device:         rrqm/s   wrqm/s     r/s     w/s   rsec/s   wsec/s avgrq-sz avgqu-sz   await  svctm  %util
sda               0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
sdb               0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
sdc               0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
sdd               0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
sde               0.00     0.00    0.10    0.00     0.80     0.00     8.00     0.00    0.00   0.00   0.00
sdf               0.00   407.50    0.00   66.80     0.00  3790.40    56.74   124.86 1524.88  13.55  90.50
sdh               0.00   406.90    0.00   66.90     0.00  3790.40    56.66    92.89 1230.52  13.21  88.40
sdi               0.00   407.80    5.50   70.20    44.00  3824.00    51.10   113.83 1333.84  12.34  93.40
sdg               0.00   406.80    6.10   71.60    48.80  3827.20    49.88    64.32  787.68  11.69  90.80
md0               0.00     0.00   11.50 1484.60    92.00 11876.80     8.00     0.00    0.00   0.00   0.00
dm-0              0.00     0.00   11.50 1484.70    92.00 11877.60     8.00  5331.18  471.91   0.63  94.70
md1               0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00

So basically lots of writes, plenty of IO wait.

So right now the box is idle, I have suspended all jobs.

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           0.00    0.00    0.00    0.00    0.00  100.00

Device:         rrqm/s   wrqm/s     r/s     w/s   rsec/s   wsec/s avgrq-sz avgqu-sz   await  svctm  %util
sda               0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
sdb               0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
sdc               0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
sdd               0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
sde               0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
sdf               0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
sdh               0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
sdi               0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
sdg               0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
md0               0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
md1               0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
dm-0              0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00

Looks peachy!

$ sudo hdparm -T -t /dev/sd[a-i]

/dev/sda:
 Timing cached reads:   2532 MB in  2.00 seconds = 1265.95 MB/sec
 Timing buffered disk reads:  270 MB in  3.02 seconds =  89.53 MB/sec

/dev/sdb:
 Timing cached reads:   2516 MB in  2.00 seconds = 1258.07 MB/sec
 Timing buffered disk reads:  264 MB in  3.02 seconds =  87.37 MB/sec

/dev/sdc:
 Timing cached reads:   2442 MB in  2.00 seconds = 1220.80 MB/sec
 Timing buffered disk reads:  272 MB in  3.00 seconds =  90.60 MB/sec

/dev/sdd:
 Timing cached reads:   2520 MB in  2.00 seconds = 1259.64 MB/sec
 Timing buffered disk reads:  272 MB in  3.02 seconds =  90.07 MB/sec

/dev/sde:
 Timing cached reads:   2524 MB in  2.00 seconds = 1261.48 MB/sec
 Timing buffered disk reads:  306 MB in  3.01 seconds = 101.56 MB/sec

/dev/sdf:
 Timing cached reads:   2366 MB in  2.00 seconds = 1183.28 MB/sec
 Timing buffered disk reads:  388 MB in  3.01 seconds = 128.88 MB/sec

/dev/sdg:
 Timing cached reads:   2536 MB in  2.00 seconds = 1267.52 MB/sec
 Timing buffered disk reads:  400 MB in  3.00 seconds = 133.12 MB/sec

/dev/sdh:
 Timing cached reads:   2538 MB in  2.00 seconds = 1269.08 MB/sec
 Timing buffered disk reads:  426 MB in  3.00 seconds = 141.90 MB/sec

/dev/sdi:
 Timing cached reads:   2538 MB in  2.00 seconds = 1268.57 MB/sec
 Timing buffered disk reads:  402 MB in  3.01 seconds = 133.69 MB/sec

Best Answer

Unfortunately the stripe cache only applies to RAID5 and 6 - there's no equivalent for RAID 0/1/10.

Performance of your individual drives (as per hdparm) looks fine - they're all performing as expected for drives of that class.

My suggestions:

  1. Check that AHCI is enabled in the BIOS and that the internally-installed drives aren't using legacy IDE mode. There is a hacked BIOS for the MicroServer available that also enables AHCI for the eSATA port too (see this link for more info) - may be worth investigating for the drives in the external enclosure, although they'll still be limited by being behind a port multiplier.
  2. Enable NCQ for all drives and see if that makes a difference (it might, it might not).
  3. Make sure the filesystem settings are optimised (mounting noatime, nodiratime). You could also disable write barriers, but that may be too risky.
  4. Check if you see any benefit from switching I/O scheduler (noop may help here).
  5. Adjust the read-ahead buffer for both the md and LVM devices: blockdev --setra <size> /dev/md1 for example (where <size> is 512-byte sectors). That will only help reads though.

Two other things that can impact performance are partition alignment and filesystem creation parameters (stride, etc) but as you're using modern tools, that shouldn't be an issue.