1/* 2** Copyright 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/* 18 * Some quick and dirty micro-benchmarks 19 */ 20 21#include <stdlib.h> 22#include <stdio.h> 23#include <errno.h> 24#include <sys/uio.h> 25#include <unistd.h> 26#include <sys/time.h> 27#include <stdint.h> 28#include <string.h> 29 30/* tv2 -= tv1 */ 31static void tv_sub(struct timeval *tv2, struct timeval *tv1) { 32 tv2->tv_sec -= tv1->tv_sec; 33 tv2->tv_usec -= tv1->tv_usec; 34 while (tv2->tv_usec < 0) { 35 tv2->tv_usec += 1000000; 36 tv2->tv_sec -= 1; 37 } 38} 39 40static int do_sleep(int iters, int delay) { 41 struct timeval tv1; 42 struct timeval tv2; 43 int i; 44 45 for (i = 0; iters == -1 || i < iters; i++) { 46 gettimeofday(&tv1, NULL); 47 sleep(delay); 48 gettimeofday(&tv2, NULL); 49 50 tv_sub(&tv2, &tv1); 51 52 printf("sleep(%d) took %ld.%06ld seconds\n", delay, tv2.tv_sec, tv2.tv_usec); 53 } 54 55 return 0; 56} 57 58int cpu_foo; 59 60static int do_cpu(int iters, int a) { 61 struct timeval tv1; 62 struct timeval tv2; 63 int i; 64 65 for (i = 0; iters == -1 || i < iters; i++) { 66 gettimeofday(&tv1, NULL); 67 for (cpu_foo = 0; cpu_foo < 100000000; cpu_foo++); 68 gettimeofday(&tv2, NULL); 69 70 tv_sub(&tv2, &tv1); 71 72 printf("cpu took %ld.%06ld seconds\n", tv2.tv_sec, tv2.tv_usec); 73 } 74 return 0; 75} 76 77static double mb_sec(unsigned long bytes, struct timeval *delta) { 78 unsigned long us = delta->tv_sec * 1000000 + delta->tv_usec; 79 return (double)bytes * 1000000.0 / 1048576.0 / (double)us; 80} 81 82static int do_memset(int iters, int sz) { 83 struct timeval tv1; 84 struct timeval tv2; 85 int i, j; 86 87 uint8_t *b = malloc(sz); 88 if (!b) return -1; 89 int c = 1000000000/sz; 90 91 for (i = 0; iters == -1 || i < iters; i++) { 92 gettimeofday(&tv1, NULL); 93 for (j = 0; j < c; j++) 94 memset(b, 0, sz); 95 96 gettimeofday(&tv2, NULL); 97 98 tv_sub(&tv2, &tv1); 99 100 printf("memset %dx%d bytes took %ld.%06ld seconds (%f MB/s)\n", 101 c, sz, tv2.tv_sec, tv2.tv_usec, mb_sec(c*sz, &tv2)); 102 } 103 return 0; 104} 105 106static int do_memcpy(int iters, int sz) { 107 struct timeval tv1; 108 struct timeval tv2; 109 int i, j; 110 111 uint8_t *a = malloc(sz); 112 if (!a) return -1; 113 uint8_t *b = malloc(sz); 114 if (!b) return -1; 115 int c = 1000000000/sz; 116 117 for (i = 0; iters == -1 || i < iters; i++) { 118 gettimeofday(&tv1, NULL); 119 for (j = 0; j < c; j++) 120 memcpy(b, a, sz); 121 122 gettimeofday(&tv2, NULL); 123 124 tv_sub(&tv2, &tv1); 125 126 printf("memcpy %dx%d bytes took %ld.%06ld seconds (%f MB/s)\n", 127 c, sz, tv2.tv_sec, tv2.tv_usec, mb_sec(c*sz, &tv2)); 128 } 129 return 0; 130} 131 132int foo; 133 134static int do_memread(int iters, int sz) { 135 struct timeval tv1; 136 struct timeval tv2; 137 int i, j, k; 138 139 int *b = malloc(sz); 140 if (!b) return -1; 141 int c = 1000000000/sz; 142 143 for (i = 0; iters == -1 || i < iters; i++) { 144 gettimeofday(&tv1, NULL); 145 for (j = 0; j < c; j++) 146 for (k = 0; k < sz/4; k++) 147 foo = b[k]; 148 149 gettimeofday(&tv2, NULL); 150 151 tv_sub(&tv2, &tv1); 152 153 printf("read %dx%d bytes took %ld.%06ld seconds (%f MB/s)\n", 154 c, sz, tv2.tv_sec, tv2.tv_usec, mb_sec(c*sz, &tv2)); 155 } 156 return 0; 157} 158 159struct { 160 char *name; 161 int (*ptr)(int, int); 162} function_table[] = { 163 {"sleep", do_sleep}, 164 {"cpu", do_cpu}, 165 {"memset", do_memset}, 166 {"memcpy", do_memcpy}, 167 {"memread", do_memread}, 168 {NULL, NULL}, 169}; 170 171static void usage() { 172 int i; 173 174 printf("Usage:\n"); 175 for (i = 0; function_table[i].name; i++) { 176 printf("\tmicro_bench %s ARG [ITERS]\n", function_table[i].name); 177 } 178} 179 180int main(int argc, char **argv) { 181 int i; 182 int iters; 183 184 if (argc < 3 || argc > 4) { 185 usage(); 186 return -1; 187 } 188 if (argc == 3) { 189 iters = -1; 190 } else { 191 iters = atoi(argv[3]); 192 } 193 for (i = 0; function_table[i].name; i++) { 194 if (!strcmp(argv[1], function_table[i].name)) { 195 printf("%s\n", function_table[i].name); 196 return (*function_table[i].ptr)(iters, atoi(argv[2])); 197 } 198 } 199 usage(); 200 return -1; 201} 202