/* ** Copyright 2010 The Android Open Source Project ** ** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. ** You may obtain a copy of the License at ** ** http://www.apache.org/licenses/LICENSE-2.0 ** ** Unless required by applicable law or agreed to in writing, software ** distributed under the License is distributed on an "AS IS" BASIS, ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ** See the License for the specific language governing permissions and ** limitations under the License. */ /* * Some quick and dirty micro-benchmarks */ #include #include #include #include #include #include #include #include /* tv2 -= tv1 */ static void tv_sub(struct timeval *tv2, struct timeval *tv1) { tv2->tv_sec -= tv1->tv_sec; tv2->tv_usec -= tv1->tv_usec; while (tv2->tv_usec < 0) { tv2->tv_usec += 1000000; tv2->tv_sec -= 1; } } static int do_sleep(int iters, int delay) { struct timeval tv1; struct timeval tv2; int i; for (i = 0; iters == -1 || i < iters; i++) { gettimeofday(&tv1, NULL); sleep(delay); gettimeofday(&tv2, NULL); tv_sub(&tv2, &tv1); printf("sleep(%d) took %ld.%06ld seconds\n", delay, tv2.tv_sec, tv2.tv_usec); } return 0; } int cpu_foo; static int do_cpu(int iters, int a) { struct timeval tv1; struct timeval tv2; int i; for (i = 0; iters == -1 || i < iters; i++) { gettimeofday(&tv1, NULL); for (cpu_foo = 0; cpu_foo < 100000000; cpu_foo++); gettimeofday(&tv2, NULL); tv_sub(&tv2, &tv1); printf("cpu took %ld.%06ld seconds\n", tv2.tv_sec, tv2.tv_usec); } return 0; } static double mb_sec(unsigned long bytes, struct timeval *delta) { unsigned long us = delta->tv_sec * 1000000 + delta->tv_usec; return (double)bytes * 1000000.0 / 1048576.0 / (double)us; } static int do_memset(int iters, int sz) { struct timeval tv1; struct timeval tv2; int i, j; uint8_t *b = malloc(sz); if (!b) return -1; int c = 1000000000/sz; for (i = 0; iters == -1 || i < iters; i++) { gettimeofday(&tv1, NULL); for (j = 0; j < c; j++) memset(b, 0, sz); gettimeofday(&tv2, NULL); tv_sub(&tv2, &tv1); printf("memset %dx%d bytes took %ld.%06ld seconds (%f MB/s)\n", c, sz, tv2.tv_sec, tv2.tv_usec, mb_sec(c*sz, &tv2)); } return 0; } static int do_memcpy(int iters, int sz) { struct timeval tv1; struct timeval tv2; int i, j; uint8_t *a = malloc(sz); if (!a) return -1; uint8_t *b = malloc(sz); if (!b) return -1; int c = 1000000000/sz; for (i = 0; iters == -1 || i < iters; i++) { gettimeofday(&tv1, NULL); for (j = 0; j < c; j++) memcpy(b, a, sz); gettimeofday(&tv2, NULL); tv_sub(&tv2, &tv1); printf("memcpy %dx%d bytes took %ld.%06ld seconds (%f MB/s)\n", c, sz, tv2.tv_sec, tv2.tv_usec, mb_sec(c*sz, &tv2)); } return 0; } int foo; static int do_memread(int iters, int sz) { struct timeval tv1; struct timeval tv2; int i, j, k; int *b = malloc(sz); if (!b) return -1; int c = 1000000000/sz; for (i = 0; iters == -1 || i < iters; i++) { gettimeofday(&tv1, NULL); for (j = 0; j < c; j++) for (k = 0; k < sz/4; k++) foo = b[k]; gettimeofday(&tv2, NULL); tv_sub(&tv2, &tv1); printf("read %dx%d bytes took %ld.%06ld seconds (%f MB/s)\n", c, sz, tv2.tv_sec, tv2.tv_usec, mb_sec(c*sz, &tv2)); } return 0; } struct { char *name; int (*ptr)(int, int); } function_table[] = { {"sleep", do_sleep}, {"cpu", do_cpu}, {"memset", do_memset}, {"memcpy", do_memcpy}, {"memread", do_memread}, {NULL, NULL}, }; static void usage() { int i; printf("Usage:\n"); for (i = 0; function_table[i].name; i++) { printf("\tmicro_bench %s ARG [ITERS]\n", function_table[i].name); } } int main(int argc, char **argv) { int i; int iters; if (argc < 3 || argc > 4) { usage(); return -1; } if (argc == 3) { iters = -1; } else { iters = atoi(argv[3]); } for (i = 0; function_table[i].name; i++) { if (!strcmp(argv[1], function_table[i].name)) { printf("%s\n", function_table[i].name); return (*function_table[i].ptr)(iters, atoi(argv[2])); } } usage(); return -1; }