Testing my hard disk speed

I wanted to know how good (or bad) my WD Caviar Green 1TB WD10EARS hard disks perform and did some tests:

# hdparm -T /dev/sdb
/dev/sdb:
Timing cached reads:   9914 MB in  2.00 seconds = 4960.19 MB/sec
# hdparm -t /dev/sdb
/dev/sdb:
Timing buffered disk reads:  260 MB in  3.02 seconds =  86.16 MB/sec

I used dd for testing write speed:

# dd if=/dev/zero of=/tmp/testimg.img bs=4k count=256k
262144+0 records in
262144+0 records out
1073741824 Bytes (1.1 GB) copied, 8.23401 s, 130 MB/s

Interesting enough, writes seem to be faster than reads. But this can be due to the fact that these drives write physical 4KB sectors and hdparm does not know about this. WD claims a throughput of 111 MB/s on the spec sheet.

Finally I wanted to test the seek times and found a nice little tool on the internet. The source will be given at the end of this post for those who are interested. Note: seeker works for me on my hardware with 11.3. It may destroy your HDD. Use at your own risk and have backups ready (as always). My result:

# ./seeker /dev/sdb 30
Seeker v3.0, 2009-06-17
http://www.linuxinsight.com/how_fast_is_your_disk.html
Benchmarking /dev/sdb
[1953525168 blocks, 1000204886016 bytes,
 931 GB, 953869 MB, 1000 GiB, 1000204 MiB]
[512 logical sector size, 512 physical sector size]
[1 threads]
Wait 30 seconds
..............................
Results: 67 seeks/second, 14.866 ms random access time
         (78973440 < offsets < 1000138063872)

# ./seeker /dev/sdb 30 24 
Seeker v3.0, 2009-06-17
http://www.linuxinsight.com/how_fast_is_your_disk.html
Benchmarking /dev/sdb
[1953525168 blocks, 1000204886016 bytes,
 931 GB, 953869 MB, 1000 GiB, 1000204 MiB]
[512 logical sector size, 512 physical sector size]
[24 threads]
Wait 30 seconds
..............................
Results: 118 seeks/second, 8.460 ms random access time
         (294353920 < offsets < 1000069917184)

This is not overwhelming at all, but had to be expected due to the slow rotational speed. I do not want to start the general HDD speed contest here, but want to share my results. I think they are as good as they can be and no further tweaking of HDD parameters is indicated. Have fun doing your own testing.

C-source for program seeker. You have to compile your own. Use at your own risk.

/* seeker.c
   ========
   
   Version:    3.0
   About:      Tool for testing hard disk seek times
   Author:     admin LinuxInsight
   Changed by: Witold Baryluk and mindbender
   Source:     http://www.linuxinsight.com/how_fast_is_your_disk.html
   Licence:    GPLv2
   Compile:    gcc -o seeker -O2 -march=x86-64 seeker.c -pthread
   Run:        seeker <device> <timeout_seconds> [number_of_threads]
               (as root)
   Example:    ./seeker /dev/sda 30 4
 */

#define _LARGEFILE64_SOURCE

#ifndef _REENTRANT
#define _REENTRANT
#endif

#include <pthread.h>
#include <stdio.h>  
#include <stdlib.h> 
#include <sys/types.h>
#include <unistd.h>   
#include <errno.h>    
#include <time.h>     
#include <signal.h>   
#include <sys/fcntl.h>
#include <sys/ioctl.h>
#include <linux/fs.h> 

#define BLOCKSIZE 512
#define O_DIRECT 00040000

pthread_mutex_t muteks = PTHREAD_MUTEX_INITIALIZER;

int count;
int TIMEOUT;
time_t start;
off64_t maxoffset = 0;
off64_t minoffset = 249994674176000uLL;

int threads;

typedef struct {
        int id; 
        int fd; 
        int run;
        char* filename;
        unsigned int seed;
        unsigned long long numbytes;
        char* buffer;
        int count;   
        off64_t maxoffset;
        off64_t minoffset;
} parm;

parm *p;

void done() {
        int i;
        time_t end;
        time(&end);

        if (end < start + TIMEOUT) {
                printf(".");
                alarm(1);   
                return;     
        }
        for (i = 0; i < threads; i++) {
                p*.run = 0;
        }
}

void report() {
        if (count) {
                printf(".
Results: %d seeks/second, %.3f ms random access "
                        "time
         (%llu < offsets < %llu)
",
                        count / TIMEOUT, 1000.0 * TIMEOUT / count, 
                        (unsigned long long)minoffset,
                        (unsigned long long)maxoffset);
        }
        exit(EXIT_SUCCESS);
}
 
void handle(const char *string, int error) {
        if (error) {
                perror(string);
                exit(EXIT_FAILURE);
        }
}

void* f(void *arg) {
        int retval; 
        off64_t offset;
        parm *p = (parm*)arg;
        srand(p->seed);

        /* wait for all processes */
        pthread_mutex_lock(&muteks);
        pthread_mutex_unlock(&muteks);

        while (p->run) {
                offset = (off64_t) ( (unsigned long long) (p->numbytes *
                        (rand_r(&(p->seed)) / (RAND_MAX + 1.0) )));
                /* do blocksize aligned seeks */
                offset = offset & (~((off64_t) 0) & (~(BLOCKSIZE-1))) ;
                /* printf("%d %x
", p->id, (unsigned long long )offset); */
                retval = lseek64(p->fd, offset, SEEK_SET);
                handle("lseek64", retval == (off64_t) -1);
                retval = read(p->fd, p->buffer, BLOCKSIZE);
                handle("read", retval < 0);
                p->count++;

                if (offset > p->maxoffset) {
                        p->maxoffset = offset;
                } else if (offset < p->minoffset) {
                        p->minoffset = offset;
                }
        }

        return NULL;
}

int main(int argc, char **argv) {
        int fd, retval;
        int physical_sector_size = 0;
        size_t logical_sector_size = 0ULL;
        unsigned long long numblocks, numbytes;
        unsigned long long ull;
        unsigned long ul;
        pthread_t *t_id; 
        pthread_attr_t pthread_custom_attr;
        int i;

        setvbuf(stdout, NULL, _IONBF, 0);

        printf("Seeker v3.0, 2009-06-17
"
                "http://www.linuxinsight.com/how_fast_is_your_disk.html
");

        if (!(argc == 3 || argc == 4)) {
                printf("Usage: %s device seconds [threads]
", argv[0]);
                exit(1);
        }

        TIMEOUT = atoi(argv[2]);

        threads = 1;
        if (argc == 4) {
                threads = atoi(argv[3]);
        }

        fd = open(argv[1], O_RDONLY | O_LARGEFILE | O_DIRECT);
        handle("open", fd < 0);

#ifdef BLKGETSIZE64
        retval = ioctl(fd, BLKGETSIZE64, &ull);
        numbytes = (unsigned long long)ull;
#else
        retval = ioctl(fd, BLKGETSIZE, &ul);
        numbytes = (unsigned long long)ul;  
#endif

        handle("ioctl", retval == -1);
        retval = ioctl(fd, BLKBSZGET, &logical_sector_size);
        handle("ioctl", retval == -1 && logical_sector_size > 0);
        retval = ioctl(fd, BLKSSZGET, &physical_sector_size);
        handle("ioctl", retval == -1 && physical_sector_size > 0);
        numblocks = ((unsigned long long) numbytes) /
                (unsigned long long)BLOCKSIZE;
        printf("Benchmarking %s
%llu blocks, %llu bytes,
 "
                "%llu GB, %llu MB, %llu GiB, %llu MiB]
",
                argv[1], numblocks, numbytes,
                numbytes/(1024uLL*1024uLL*1024uLL),
                numbytes / (1024uLL*1024uLL),
                numbytes/(1000uLL*1000uLL*1000uLL),
                numbytes / (1000uLL*1000uLL));
        printf("%d logical sector size, %d physical sector size]
",
                physical_sector_size, physical_sector_size);
        printf("%d threads]
", threads);
        printf("Wait %d seconds
", TIMEOUT);

        t_id = (pthread_t *)malloc(threads*sizeof(pthread_t));
        handle("malloc", t_id == NULL);
        pthread_attr_init(&pthread_custom_attr);
        p = (parm *)malloc(sizeof(parm)*threads);
        handle("malloc", p == NULL);

        time(&start);

        pthread_mutex_lock(&muteks);

        srand((unsigned int)start*(unsigned int)getpid());

        for (i = 0; i < threads; i++) {
                p*.id = i;
                p*.filename = argv[1];
                p*.seed = rand()+i;   
                p*.fd = dup(fd);      
                handle("dup", p*.fd < 0);
                p*.buffer = (char *) memalign(512*8, sizeof(char)*BLOCKSIZE);
                /* printf("%x
", (int)(&(p*.buffer))); */
                p*.numbytes = numbytes;
                handle("malloc", p*.buffer == NULL);
                p*.run = 1;
                p*.count = 0;
                p*.minoffset = minoffset;
                p*.maxoffset = maxoffset;

                retval = pthread_create(&(t_id*), NULL, f, (void*)(p+i));
                handle("pthread_create", retval != 0);
        }

        sleep(1);

        time(&start);
        signal(SIGALRM, &done);
        alarm(1);

        pthread_mutex_unlock(&muteks);

        for (i = 0; i < threads; i++) {
                pthread_join(t_id*, NULL);
        }

        for (i = 0; i < threads; i++) {
                count += p*.count;   
                if (p*.maxoffset > maxoffset) {
                        maxoffset = p*.maxoffset;
                }
                if (p*.minoffset < minoffset) {
                        minoffset = p*.minoffset;
                }
        }

        report();

        /* notreached */
        return 0;
}

Wow your HDD is fast! Here is mine:


andrew-desktop:~ # hdparm -Tt /dev/sda

/dev/sda:
 Timing cached reads:   7684 MB in  2.00 seconds = 3845.72 MB/sec
 Timing buffered disk reads:  232 MB in  3.01 seconds =  77.06 MB/sec

I haven’t tried out seeker yet though*********************

OK vodoo, you got me hooked. I am not running anything at my own risk, but here is a couple of tests on my main Hard Drive (WD 600GB, 10K RPM - External eSATA):

hdparm -T /dev/sdb

/dev/sdb:
 Timing cached reads:   12300 MB in  2.00 seconds = 6156.34 MB/sec

hdparm -t /dev/sdb

/dev/sdb:
 Timing buffered disk reads:  436 MB in  3.00 seconds = 145.26 MB/sec

This is my internal Windows Drive (Segate 2TB - 7200 RPM):

hdparm -T /dev/sda

/dev/sda:
 Timing cached reads:   12768 MB in  2.00 seconds = 6391.08 MB/sec

hdparm -t /dev/sda

/dev/sda:
 Timing buffered disk reads:  392 MB in  3.01 seconds = 130.17 MB/sec

And Finally, my USB 3 External Drive (Segate 1.5 TB - 5200 RPM):

hdparm -T /dev/sdc

/dev/sdc:
 Timing cached reads:   12612 MB in  2.00 seconds = 6312.97 MB/sec

hdparm -t /dev/sdc

/dev/sdc:
 Timing buffered disk reads:  286 MB in  3.00 seconds =  95.24 MB/sec

Did not do them all, but perhaps something to compare to.

Thank You,

All are some flavor of WD caviar green 500gig drives

fuuyuu:/home/flamebait # hdparm -T /dev/sda

/dev/sda:
Timing cached reads: 7024 MB in 2.00 seconds = 3512.61 MB/sec
fuuyuu:/home/flamebait # hdparm -T /dev/sdb

/dev/sdb:
Timing cached reads: 7384 MB in 2.00 seconds = 3692.80 MB/sec
fuuyuu:/home/flamebait # hdparm -T /dev/sdc

/dev/sdc:
Timing cached reads: 7028 MB in 2.00 seconds = 3514.52 MB/sec
fuuyuu:/home/flamebait # hdparm -T /dev/sdd

/dev/sdd:
Timing cached reads: 7282 MB in 2.00 seconds = 3642.47 MB/sec
fuuyuu:/home/flamebait # hdparm -T /dev/sde

/dev/sde:
Timing cached reads: 7442 MB in 2.00 seconds = 3722.57 MB/sec
fuuyuu:/home/flamebait # hdparm -T /dev/sdf

/dev/sdf:
Timing cached reads: 7274 MB in 2.00 seconds = 3638.20 MB/sec

They are plenty fast for me.

I wonder why my one is so slow. Must just be the hard drive (Seagate ST3320620AS)

On 2010-09-28 15:36, vodoo wrote:

> I wanted to know how good (or bad) my WD Caviar Green 1TB WD10EARS hard
> disks perform and did some tests:

> Timing buffered disk reads: 260 MB in 3.02 seconds = 86.16 MB/sec
> --------------------

Typically you use “-tT” in the same line.

> I used dd for testing write speed:

You would have to mount the partition “sync”, to disable caching.


Cheers / Saludos,

Carlos E. R.
(from 11.2 x86_64 “Emerald” at Telcontar)

On 2010-09-29 03:06, FlameBait wrote:
>
> All are some flavor of WD caviar green 500gig drives
>
> fuuyuu:/home/flamebait # hdparm -T /dev/sda
>
> /dev/sda:
> Timing cached reads: 7024 MB in 2.00 seconds = 3512.61 MB/sec
> fuuyuu:/home/flamebait # hdparm -T /dev/sdb

> They are plenty fast for me.

Yes, because you are using “-T” only, which only measures in-memory speed. The cache speed. That’s
not the disk speed you are measuring :stuck_out_tongue:


Cheers / Saludos,

Carlos E. R.
(from 11.2 x86_64 “Emerald” at Telcontar)

Setting the flag to -tT shows about 90mbt average across all the drives with buffered reads still plenty fast for me and my usage.
The difference in heat, noise and power consumption is what make the green drives attractive. They are a darned lot better speed and price wise than my frist HD was it was :stuck_out_tongue: 40 megs for 400 dollars and SLOW.

Here are the results from my laptop which is even slower than my desktop :frowning:


andrew-laptop:~ # hdparm -Tt /dev/sda

/dev/sda:
 Timing cached reads:   2454 MB in  2.00 seconds = 1227.59 MB/sec
 Timing buffered disk reads:  254 MB in  3.02 seconds =  84.22 MB/sec

@jdmcdaniel3: your results clearly show that drives turning at a higher RPM are faster.

@ah7013: considering that your 320GB drive may be of some age it performs quite well. And your laptop is even faster than the desktop for buffered disk reads.

Anyone going to compare the seek times? I expect smaller drives doing even better here than the larger ones.

vodoo wrote:

…snip…
>
> Anyone going to compare the seek times? I expect smaller drives doing
> even better here than the larger ones.

Sounds reasonable… BUT, with the increase in density that often times
accompanies larger drives, the seeks can be fewer and/or smaller… so
sometimes it’s simply a wash.

Sounds reasonable… BUT, with the increase in density that often times accompanies larger drives, the seeks can be fewer and/or smaller… so sometimes it’s simply a wash.

Yep, you are right. Real life may have a complete database on one or two tracks. But as far as I understand the ‘seeker’ program, it seeks randomly within the available disk space, and the larger the disk is, the slower the average seek time will be. This test assumes that you have a huge database filling the whole hard disk and that you are seeking randomly within it.

Yes the 320GB hard drive is about 3 years old. the 500GB is a few months old

On 2010-10-02 17:06, vodoo wrote:

> Anyone going to compare the seek times? I expect smaller drives doing
> even better here than the larger ones.

Or not. The voice coil has greater power, thus faster seek.


Cheers / Saludos,

Carlos E. R.
(from 11.2 x86_64 “Emerald” at Telcontar)

Or not. The voice coil has greater power, thus faster seek.

That’s exactly why I would like to see some results. I made a guess, but I don’t know the answer.

On 2010-10-04 00:36, vodoo wrote:
>
>> Or not. The voice coil has greater power, thus faster seek.
>
> That’s exactly why I would like to see some results. I made a guess,
> but I don’t know the answer.

No way, because of that little warning about destruction of data >:-)


Cheers / Saludos,

Carlos E. R.
(from 11.2 x86_64 “Emerald” at Telcontar)