HDParm

hdparm is a tool that allows you to tweak various parameters of hard drives and optical drives. Depending on the drive, you can get very high results.


Base Drive, no options on

This is our base drive. I reset it back to no options for this demonstration. (Note all commands were run as root)

hdparm -d0 -c0 -m0 -u0 /dev/hdb
 /dev/hdb:
 setting 32-bit IO_support flag to 0
 setting multcount to 0
 setting unmaskirq to 0 (off)
 setting using_dma to 0 (off)
 multcount    =  0 (off)
 IO_support   =  0 (default 16-bit)
 unmaskirq    =  0 (off)
 using_dma    =  0 (off)
    

Timings

Now to get the timings for the drive. This is done with hdparm's -Tt options. In order for a decent timing, I ran them 5 times in a row

for i in $(seq 1 1 5);do;hdparm -Tt /dev/hdb; done
 /dev/hdb:
 Timing cached reads:   464 MB in  2.00 seconds = 232.00 MB/sec
 Timing buffered disk reads:   10 MB in  3.77 seconds =   2.65 MB/sec

/dev/hdb:
 Timing cached reads:   440 MB in  2.01 seconds = 219.32 MB/sec
 Timing buffered disk reads:   10 MB in  3.73 seconds =   2.68 MB/sec

/dev/hdb:
 Timing cached reads:   440 MB in  2.01 seconds = 219.33 MB/sec
 Timing buffered disk reads:   10 MB in  3.63 seconds =   2.76 MB/sec

/dev/hdb:
 Timing cached reads:   434 MB in  2.01 seconds = 216.27 MB/sec
 Timing buffered disk reads:    8 MB in  3.10 seconds =   2.58 MB/sec

/dev/hdb:
 Timing cached reads:   448 MB in  2.00 seconds = 223.74 MB/sec
 Timing buffered disk reads:   10 MB in  3.76 seconds =   2.66 MB/sec
  

You can see there are variances in the timings, but on average we are getting around 220 MB/sec on cached reads and 2.60 MB/sec on buffered reads.

MultiSector I/O

One option to tweak is the Multiple Sector I/O setting (aka IDE Block Mode). This allows the transfer of multiple sectors per I/O interrupt. You can find out what the max rated MultiSector I/O for the device is with hdparm -i DEVICE and looking at the MaxMultiSect field. Typically this will be around 16 for newer drives. You set it with the -m option

hdparm -u0 -d0 -c0 -m16 /dev/hdb
 /dev/hdb:
 setting 32-bit IO_support flag to 0
 setting multcount to 16
 setting unmaskirq to 0 (off)
 setting using_dma to 0 (off)
 multcount    = 16 (on)
 IO_support   =  0 (default 16-bit)
 unmaskirq    =  0 (off)
 using_dma    =  0 (off)
  

And we rerun the timings

for i in $(seq 1 1 5);do;hdparm -Tt /dev/hdb; done
 /dev/hdb:
 Timing cached reads:   462 MB in  2.00 seconds = 230.88 MB/sec
 Timing buffered disk reads:    8 MB in  3.09 seconds =   2.59 MB/sec

/dev/hdb:
 Timing cached reads:   406 MB in  2.01 seconds = 202.23 MB/sec
 Timing buffered disk reads:    8 MB in  3.11 seconds =   2.57 MB/sec

/dev/hdb:
 Timing cached reads:   440 MB in  2.00 seconds = 219.59 MB/sec
 Timing buffered disk reads:    8 MB in  3.24 seconds =   2.47 MB/sec

/dev/hdb:
 Timing cached reads:   460 MB in  2.01 seconds = 229.34 MB/sec
 Timing buffered disk reads:    8 MB in  3.70 seconds =   2.16 MB/sec

/dev/hdb:
 Timing cached reads:   464 MB in  2.01 seconds = 231.01 MB/sec
 Timing buffered disk reads:    8 MB in  3.27 seconds =   2.45 MB/sec
  

Not much if any increase. Interestingly enough, according to the hdparm manpage, Western Digital drives seem to perform better with MultiSector options of 4 or 8. This is a WD drive, but I didn't investigate the other settings. It should be noted that the impact on my system decreased though

Interrupt Unmask

This is an interesting option that doesn't actually give a speed boost to the drive itself, but rather improves overall system performance. Turning this on allows the driver to unmask other interrupts while processing a disk interrupt. It is handled with the -u option

hdparm -u1 -c0 -d0 -m16 /dev/hdb
 /dev/hdb:
 setting 32-bit IO_support flag to 0
 setting multcount to 16
 setting unmaskirq to 1 (on)
 setting using_dma to 0 (off)
 multcount    = 16 (on)
 IO_support   =  0 (default 16-bit)
 unmaskirq    =  1 (on)
 using_dma    =  0 (off)
  

And again we time..

for i in $(seq 1 1 5);do;hdparm -Tt /dev/hdb;done
 /dev/hdb:
 Timing cached reads:   462 MB in  2.00 seconds = 230.67 MB/sec
 Timing buffered disk reads:    8 MB in  3.32 seconds =   2.41 MB/sec

/dev/hdb:
 Timing cached reads:   430 MB in  2.00 seconds = 214.88 MB/sec
 Timing buffered disk reads:    8 MB in  3.12 seconds =   2.56 MB/sec

/dev/hdb:
 Timing cached reads:   440 MB in  2.01 seconds = 219.28 MB/sec
 Timing buffered disk reads:    8 MB in  3.31 seconds =   2.42 MB/sec

/dev/hdb:
 Timing cached reads:   472 MB in  2.01 seconds = 235.20 MB/sec
 Timing buffered disk reads:    8 MB in  3.17 seconds =   2.53 MB/sec

/dev/hdb:
 Timing cached reads:   468 MB in  2.00 seconds = 233.77 MB/sec
 Timing buffered disk reads:    8 MB in  3.19 seconds =   2.51 MB/sec
  

Again not much of an increase in speed itself, but again the impact on the machine decreased

32-bit I/O

This one makes sense. This sets the drive's 32-bit I/O support. It makes sense that 32-bit I/O would be faster than 16-bit I/O. It should be noted that this option has 3 values. -c0 turns it off, -c1 enables it, and -c3 enables it with a sync sequence required by many drives, at the cost of slightly more overhead

hdparm -c3 -d0 -u1 -m16 /dev/hdb
 /dev/hdb:
 setting 32-bit IO_support flag to 3
 setting multcount to 16
 setting unmaskirq to 1 (on)
 setting using_dma to 0 (off)
 multcount    = 16 (on)
 IO_support   =  3 (32-bit w/sync)
 unmaskirq    =  1 (on)
 using_dma    =  0 (off)
  

Once more to the timings...

for i in $(seq 1 1 5);do;hdparm -Tt /dev/hdb;done
 /dev/hdb:
 Timing cached reads:   468 MB in  2.01 seconds = 233.32 MB/sec
 Timing buffered disk reads:   12 MB in  3.45 seconds =   3.48 MB/sec

/dev/hdb:
 Timing cached reads:   470 MB in  2.00 seconds = 234.80 MB/sec
 Timing buffered disk reads:   12 MB in  3.35 seconds =   3.58 MB/sec

/dev/hdb:
 Timing cached reads:   436 MB in  2.01 seconds = 217.35 MB/sec
 Timing buffered disk reads:   10 MB in  3.30 seconds =   3.03 MB/sec

/dev/hdb:
 Timing cached reads:   444 MB in  2.01 seconds = 221.20 MB/sec
 Timing buffered disk reads:   12 MB in  3.41 seconds =   3.52 MB/sec

/dev/hdb:
 Timing cached reads:   468 MB in  2.00 seconds = 233.64 MB/sec
 Timing buffered disk reads:   12 MB in  3.35 seconds =   3.59 MB/sec
  

This time we see some speed increases. Buffered Disk Reads increased to about 3.40 MB/sec

Direct Memory Access (DMA)

The best comes last. Turning on DMA is probably the reason most of us have heard of hdparm, with good reason. It gives the biggest boost out of all the hdparm tweaks. Activate it with the -d1 option

hdparm -d1 -c3 -u1 -m16 /dev/hdb
 /dev/hdb:
 setting 32-bit IO_support flag to 3
 setting multcount to 16
 setting unmaskirq to 1 (on)
 setting using_dma to 1 (on)
 multcount    = 16 (on)
 IO_support   =  3 (32-bit w/sync)
 unmaskirq    =  1 (on)
 using_dma    =  1 (on)
  

Now lets fire up the timings!

for i in $(seq 1 1 5);do;hdparm -Tt /dev/hdb;done
 /dev/hdb:
 Timing cached reads:   460 MB in  2.00 seconds = 229.60 MB/sec
 Timing buffered disk reads:   84 MB in  3.06 seconds =  27.42 MB/sec

/dev/hdb:
 Timing cached reads:   456 MB in  2.01 seconds = 227.34 MB/sec
 Timing buffered disk reads:   84 MB in  3.03 seconds =  27.73 MB/sec

/dev/hdb:
 Timing cached reads:   470 MB in  2.00 seconds = 234.93 MB/sec
 Timing buffered disk reads:   84 MB in  3.03 seconds =  27.73 MB/sec

/dev/hdb:
 Timing cached reads:   462 MB in  2.00 seconds = 230.96 MB/sec
 Timing buffered disk reads:   84 MB in  3.06 seconds =  27.41 MB/sec

/dev/hdb:
 Timing cached reads:   444 MB in  2.00 seconds = 221.87 MB/sec
 Timing buffered disk reads:   84 MB in  3.01 seconds =  27.87 MB/sec
  

Pretty damn good! Buffered disk reads increased almost 9-fold. Also there was almost no impact on system performance!

Obtaining Disk Data

One more thing, how do you get the data? Easy

hdparm -I /dev/hdb
/dev/hdb:

ATA device, with non-removable media
	Model Number:       WDC WD3000JB-00KFA0                     
	Serial Number:      WD-WMAMR1055762
	Firmware Revision:  08.05J08
Standards:
	Supported: 6 5 4 
	Likely used: 6
Configuration:
	Logical		max	current
	cylinders	16383	65535
	heads		16	1
	sectors/track	63	63
	--
	CHS current addressable sectors:    4128705
	LBA    user addressable sectors:  268435455
	LBA48  user addressable sectors:  586072368
	device size with M = 1024*1024:      286168 MBytes
	device size with M = 1000*1000:      300069 MBytes (300 GB)
Capabilities:
	LBA, IORDY(can be disabled)
	Standby timer values: spec'd by Standard, with device specific minimum
	R/W multiple sector transfer: Max = 16	Current = 16
	Recommended acoustic management value: 128, current value: 254
	DMA: mdma0 mdma1 mdma2 udma0 udma1 *udma2 udma3 udma4 udma5 
	     Cycle time: min=120ns recommended=120ns
	PIO: pio0 pio1 pio2 pio3 pio4 
	     Cycle time: no flow control=120ns  IORDY flow control=120ns
Commands/features:
	Enabled	Supported:
	   *	SMART feature set
	    	Security Mode feature set
	   *	Power Management feature set
	   *	Write cache
	   *	Look-ahead
	   *	Host Protected Area feature set
	   *	WRITE_BUFFER command
	   *	READ_BUFFER command
	   *	DOWNLOAD_MICROCODE
	    	SET_MAX security extension
	   *	Automatic Acoustic Management feature set
	   *	48-bit Address feature set
	   *	Device Configuration Overlay feature set
	   *	Mandatory FLUSH_CACHE
	   *	FLUSH_CACHE_EXT
	   *	SMART error logging
	   *	SMART self-test
	   *	SMART Command Transport (SCT) feature set
	   *	SCT Long Sector Access (AC1)
	   *	SCT LBA Segment Access (AC2)
	   *	SCT Error Recovery Control (AC3)
	   *	SCT Features Control (AC4)
Security: 
	Master password revision code = 65534
		supported
	not	enabled
	not	locked
	not	frozen
	not	expired: security count
	not	supported: enhanced erase
HW reset results:
	CBLID- above Vih
	Device num = 1 determined by the jumper
Checksum: correct

  

References:

hdparm(8)