rand_emmc_perf.c revision 2633ce5ca5024d5565c9068c29ec39a8c3ed10e9
1/* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17/* A simple test of emmc random read and write performance. When testing write 18 * performance, try it twice, once with O_SYNC compiled in, and once with it commented 19 * out. Without O_SYNC, the close(2) blocks until all the dirty buffers are written 20 * out, but the numbers tend to be higher. 21 */ 22 23#include <string.h> 24#include <stdio.h> 25#include <sys/types.h> 26#include <sys/stat.h> 27#include <fcntl.h> 28#include <sys/time.h> 29#include <stdlib.h> 30 31#define TST_BLK_SIZE 4096 32/* Number of seconds to run the test */ 33#define TEST_LEN 10 34 35static void usage(void) { 36 fprintf(stderr, "Usage: rand_emmc_perf [ -r | -w ] [-o] <size_in_mb> <block_dev>\n"); 37 exit(1); 38} 39 40int main(int argc, char *argv[]) 41{ 42 long max_blocks; 43 int fd, fd2, write_mode = 0, iops = 0; 44 struct timeval start, end, res; 45 unsigned int seed; 46 char buf[TST_BLK_SIZE] = { 0 }; 47 int c; 48 int o_sync = 0; 49 50 while ((c = getopt(argc, argv, "+rwo")) != -1) { 51 switch (c) { 52 case '?': 53 default: 54 usage(); 55 break; 56 57 case 'r': 58 /* Do nothing, read mode is the default */ 59 break; 60 61 case 'w': 62 write_mode = 1; 63 break; 64 65 case 'o': 66 o_sync = O_SYNC; 67 break; 68 } 69 } 70 71 if (o_sync && !write_mode) { 72 /* Can only specify o_sync in write mode. Probably doesn't matter, 73 * but clear o_sync if in read mode */ 74 o_sync = 0; 75 } 76 77 if ((argc - optind) != 2) { 78 usage(); 79 } 80 81 /* Size is given in megabytes, so compute the number of TST_BLK_SIZE blocks. */ 82 max_blocks = atol(argv[2]) * ((1024*1024) / TST_BLK_SIZE); 83 84 if ((fd = open(argv[3], O_RDWR | o_sync)) < 0) { 85 fprintf(stderr, "Cannot open block device %s\n", argv[2]); 86 exit(1); 87 } 88 89 fd2 = open("/dev/urandom\n", O_RDONLY); 90 if (fd2 < 0) { 91 fprintf(stderr, "Cannot open /dev/urandom\n"); 92 } 93 if (read(fd2, &seed, sizeof(seed)) != sizeof(seed)) { 94 fprintf(stderr, "Cannot read /dev/urandom\n"); 95 } 96 close(fd2); 97 srand(seed); 98 99 res.tv_sec = 0; 100 gettimeofday(&start, 0); 101 while (res.tv_sec < TEST_LEN) { 102 if (lseek64(fd, (rand() % max_blocks) * TST_BLK_SIZE, SEEK_SET) < 0) { 103 fprintf(stderr, "lseek64 failed\n"); 104 } 105 if (write_mode) { 106 if (write(fd, buf, sizeof(buf)) != sizeof(buf)) { 107 fprintf(stderr, "Short write\n"); 108 } 109 } else { 110 if (read(fd, buf, sizeof(buf)) != sizeof(buf)) { 111 fprintf(stderr, "Short read\n"); 112 } 113 } 114 iops++; 115 gettimeofday(&end, 0); 116 timersub(&end, &start, &res); 117 } 118 close(fd); 119 120 /* The close can take a while when in write_mode as buffers are flushed. 121 * So get the time again. */ 122 gettimeofday(&end, 0); 123 timersub(&end, &start, &res); 124 125 printf("%d iops/sec\n", iops / (int) res.tv_sec); 126 127 exit(0); 128} 129 130