rand_emmc_perf.c revision 2633ce5ca5024d5565c9068c29ec39a8c3ed10e9
12633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall/*
22633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall * Copyright (C) 2010 The Android Open Source Project
32633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall *
42633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall * Licensed under the Apache License, Version 2.0 (the "License");
52633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall * you may not use this file except in compliance with the License.
62633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall * You may obtain a copy of the License at
72633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall *
82633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall *      http://www.apache.org/licenses/LICENSE-2.0
92633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall *
102633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall * Unless required by applicable law or agreed to in writing, software
112633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall * distributed under the License is distributed on an "AS IS" BASIS,
122633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall * See the License for the specific language governing permissions and
142633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall * limitations under the License.
152633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall */
162633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall
172633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall/* A simple test of emmc random read and write performance.  When testing write
182633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall * performance, try it twice, once with O_SYNC compiled in, and once with it commented
192633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall * out.  Without O_SYNC, the close(2) blocks until all the dirty buffers are written
202633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall * out, but the numbers tend to be higher.
212633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall */
222633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall
232633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall#include <string.h>
242633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall#include <stdio.h>
252633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall#include <sys/types.h>
262633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall#include <sys/stat.h>
272633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall#include <fcntl.h>
282633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall#include <sys/time.h>
292633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall#include <stdlib.h>
302633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall
312633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall#define TST_BLK_SIZE 4096
322633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall/* Number of seconds to run the test */
332633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall#define TEST_LEN 10
342633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall
352633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrallstatic void usage(void) {
362633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall        fprintf(stderr, "Usage: rand_emmc_perf [ -r | -w ] [-o] <size_in_mb> <block_dev>\n");
372633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall        exit(1);
382633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall}
392633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall
402633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrallint main(int argc, char *argv[])
412633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall{
422633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall    long max_blocks;
432633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall    int fd, fd2, write_mode = 0, iops = 0;
442633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall    struct timeval start, end, res;
452633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall    unsigned int seed;
462633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall    char buf[TST_BLK_SIZE] = { 0 };
472633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall    int c;
482633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall    int o_sync = 0;
492633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall
502633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall    while ((c = getopt(argc, argv, "+rwo")) != -1) {
512633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall        switch (c) {
522633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall          case '?':
532633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall          default:
542633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall            usage();
552633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall            break;
562633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall
572633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall          case 'r':
582633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall            /* Do nothing, read mode is the default */
592633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall            break;
602633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall
612633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall          case 'w':
622633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall            write_mode = 1;
632633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall            break;
642633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall
652633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall          case 'o':
662633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall            o_sync = O_SYNC;
672633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall            break;
682633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall        }
692633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall    }
702633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall
712633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall    if (o_sync && !write_mode) {
722633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall        /* Can only specify o_sync in write mode.  Probably doesn't matter,
732633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall         * but clear o_sync if in read mode */
742633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall        o_sync = 0;
752633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall    }
762633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall
772633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall    if ((argc - optind) != 2) {
782633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall        usage();
792633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall    }
802633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall
812633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall    /* Size is given in megabytes, so compute the number of TST_BLK_SIZE blocks. */
822633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall    max_blocks = atol(argv[2]) * ((1024*1024) / TST_BLK_SIZE);
832633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall
842633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall    if ((fd = open(argv[3], O_RDWR | o_sync)) < 0) {
852633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall        fprintf(stderr, "Cannot open block device %s\n", argv[2]);
862633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall        exit(1);
872633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall    }
882633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall
892633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall    fd2 = open("/dev/urandom\n", O_RDONLY);
902633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall    if (fd2 < 0) {
912633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall        fprintf(stderr, "Cannot open /dev/urandom\n");
922633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall    }
932633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall    if (read(fd2, &seed, sizeof(seed)) != sizeof(seed)) {
942633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall        fprintf(stderr, "Cannot read /dev/urandom\n");
952633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall    }
962633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall    close(fd2);
972633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall    srand(seed);
982633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall
992633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall    res.tv_sec = 0;
1002633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall    gettimeofday(&start, 0);
1012633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall    while (res.tv_sec < TEST_LEN) {
1022633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall        if (lseek64(fd, (rand() % max_blocks) * TST_BLK_SIZE, SEEK_SET) < 0) {
1032633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall            fprintf(stderr, "lseek64 failed\n");
1042633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall        }
1052633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall        if (write_mode) {
1062633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall            if (write(fd, buf, sizeof(buf)) != sizeof(buf)) {
1072633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall                fprintf(stderr, "Short write\n");
1082633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall            }
1092633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall        } else {
1102633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall            if (read(fd, buf, sizeof(buf)) != sizeof(buf)) {
1112633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall                fprintf(stderr, "Short read\n");
1122633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall            }
1132633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall        }
1142633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall        iops++;
1152633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall        gettimeofday(&end, 0);
1162633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall        timersub(&end, &start, &res);
1172633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall    }
1182633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall    close(fd);
1192633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall
1202633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall    /* The close can take a while when in write_mode as buffers are flushed.
1212633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall     * So get the time again. */
1222633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall    gettimeofday(&end, 0);
1232633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall    timersub(&end, &start, &res);
1242633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall
1252633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall    printf("%d iops/sec\n", iops / (int) res.tv_sec);
1262633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall
1272633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall    exit(0);
1282633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall}
1292633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall
130