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 */
2232243fadeab8cf244861e3df89744b78ba3eff92Ken Sumrall
2332243fadeab8cf244861e3df89744b78ba3eff92Ken Sumrall#define _LARGEFILE64_SOURCE
242633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall#include <string.h>
252633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall#include <stdio.h>
262633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall#include <sys/types.h>
272633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall#include <sys/stat.h>
282633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall#include <fcntl.h>
292633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall#include <sys/time.h>
302633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall#include <stdlib.h>
3132243fadeab8cf244861e3df89744b78ba3eff92Ken Sumrall#include <unistd.h>
322633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall
332633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall#define TST_BLK_SIZE 4096
342633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall/* Number of seconds to run the test */
352633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall#define TEST_LEN 10
362633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall
372633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrallstatic void usage(void) {
382633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall        fprintf(stderr, "Usage: rand_emmc_perf [ -r | -w ] [-o] <size_in_mb> <block_dev>\n");
392633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall        exit(1);
402633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall}
412633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall
422633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrallint main(int argc, char *argv[])
432633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall{
44ecb600d0d9de4eacfd619dfe380a94af1abee0ddKen Sumrall    unsigned long long max_blocks;
452633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall    int fd, fd2, write_mode = 0, iops = 0;
462633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall    struct timeval start, end, res;
472633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall    unsigned int seed;
482633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall    char buf[TST_BLK_SIZE] = { 0 };
492633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall    int c;
502633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall    int o_sync = 0;
512633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall
522633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall    while ((c = getopt(argc, argv, "+rwo")) != -1) {
532633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall        switch (c) {
542633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall          case '?':
552633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall          default:
562633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall            usage();
572633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall            break;
582633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall
592633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall          case 'r':
602633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall            /* Do nothing, read mode is the default */
612633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall            break;
622633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall
632633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall          case 'w':
642633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall            write_mode = 1;
652633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall            break;
662633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall
672633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall          case 'o':
682633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall            o_sync = O_SYNC;
692633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall            break;
702633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall        }
712633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall    }
722633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall
732633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall    if (o_sync && !write_mode) {
742633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall        /* Can only specify o_sync in write mode.  Probably doesn't matter,
752633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall         * but clear o_sync if in read mode */
762633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall        o_sync = 0;
772633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall    }
782633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall
792633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall    if ((argc - optind) != 2) {
802633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall        usage();
812633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall    }
822633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall
832633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall    /* Size is given in megabytes, so compute the number of TST_BLK_SIZE blocks. */
8432243fadeab8cf244861e3df89744b78ba3eff92Ken Sumrall    max_blocks = atol(argv[optind]) * ((1024*1024) / TST_BLK_SIZE);
852633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall
8632243fadeab8cf244861e3df89744b78ba3eff92Ken Sumrall    if ((fd = open(argv[optind + 1], O_RDWR | o_sync)) < 0) {
8732243fadeab8cf244861e3df89744b78ba3eff92Ken Sumrall        fprintf(stderr, "Cannot open block device %s\n", argv[optind + 1]);
882633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall        exit(1);
892633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall    }
902633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall
9132243fadeab8cf244861e3df89744b78ba3eff92Ken Sumrall    fd2 = open("/dev/urandom", O_RDONLY);
922633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall    if (fd2 < 0) {
932633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall        fprintf(stderr, "Cannot open /dev/urandom\n");
942633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall    }
952633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall    if (read(fd2, &seed, sizeof(seed)) != sizeof(seed)) {
962633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall        fprintf(stderr, "Cannot read /dev/urandom\n");
972633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall    }
982633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall    close(fd2);
992633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall    srand(seed);
1002633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall
1012633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall    res.tv_sec = 0;
1022633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall    gettimeofday(&start, 0);
1032633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall    while (res.tv_sec < TEST_LEN) {
1042633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall        if (lseek64(fd, (rand() % max_blocks) * TST_BLK_SIZE, SEEK_SET) < 0) {
1052633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall            fprintf(stderr, "lseek64 failed\n");
1062633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall        }
1072633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall        if (write_mode) {
1082633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall            if (write(fd, buf, sizeof(buf)) != sizeof(buf)) {
1092633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall                fprintf(stderr, "Short write\n");
1102633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall            }
1112633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall        } else {
1122633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall            if (read(fd, buf, sizeof(buf)) != sizeof(buf)) {
1132633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall                fprintf(stderr, "Short read\n");
1142633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall            }
1152633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall        }
1162633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall        iops++;
1172633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall        gettimeofday(&end, 0);
1182633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall        timersub(&end, &start, &res);
1192633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall    }
1202633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall    close(fd);
1212633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall
1222633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall    /* The close can take a while when in write_mode as buffers are flushed.
1232633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall     * So get the time again. */
1242633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall    gettimeofday(&end, 0);
1252633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall    timersub(&end, &start, &res);
1262633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall
1272633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall    printf("%d iops/sec\n", iops / (int) res.tv_sec);
1282633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall
1292633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall    exit(0);
1302633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall}
1312633ce5ca5024d5565c9068c29ec39a8c3ed10e9Ken Sumrall
132