micro_bench.c revision b56034796a7cadee89c4cd5e3c0f0730193231de
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 delay) {
41    struct timeval tv1;
42    struct timeval tv2;
43
44    while (1) {
45        gettimeofday(&tv1, NULL);
46        sleep(delay);
47        gettimeofday(&tv2, NULL);
48
49        tv_sub(&tv2, &tv1);
50
51        printf("sleep(%d) took %ld.%06ld seconds\n", delay, tv2.tv_sec, tv2.tv_usec);
52    }
53
54    return 0;
55}
56
57int cpu_foo;
58
59static int do_cpu(int a) {
60    struct timeval tv1;
61    struct timeval tv2;
62
63    while (1) {
64        gettimeofday(&tv1, NULL);
65        for (cpu_foo = 0; cpu_foo < 100000000; cpu_foo++);
66        gettimeofday(&tv2, NULL);
67
68        tv_sub(&tv2, &tv1);
69
70        printf("cpu took %ld.%06ld seconds\n", tv2.tv_sec, tv2.tv_usec);
71    }
72    return 0;
73}
74
75static double mb_sec(unsigned long bytes, struct timeval *delta) {
76    unsigned long us = delta->tv_sec * 1000000 + delta->tv_usec;
77    return (double)bytes * 1000000.0 / 1048576.0 / (double)us;
78}
79
80static int do_memset(int sz) {
81    struct timeval tv1;
82    struct timeval tv2;
83    int i;
84
85    uint8_t *b = malloc(sz);
86    if (!b) return -1;
87    int c = 1000000000/sz;
88
89    while (1) {
90        gettimeofday(&tv1, NULL);
91        for (i = 0; i < c; i++)
92            memset(b, 0, sz);
93
94        gettimeofday(&tv2, NULL);
95
96        tv_sub(&tv2, &tv1);
97
98        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));
99    }
100    return 0;
101}
102
103static int do_memcpy(int sz) {
104    struct timeval tv1;
105    struct timeval tv2;
106    int i;
107
108    uint8_t *a = malloc(sz);
109    if (!a) return -1;
110    uint8_t *b = malloc(sz);
111    if (!b) return -1;
112    int c = 1000000000/sz;
113
114    while (1) {
115        gettimeofday(&tv1, NULL);
116        for (i = 0; i < c; i++)
117            memcpy(b, a, sz);
118
119        gettimeofday(&tv2, NULL);
120
121        tv_sub(&tv2, &tv1);
122
123        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));
124    }
125    return 0;
126}
127
128int foo;
129
130static int do_memread(int sz) {
131    struct timeval tv1;
132    struct timeval tv2;
133    int i, j;
134
135    int *b = malloc(sz);
136    if (!b) return -1;
137    int c = 1000000000/sz;
138
139    while (1) {
140        gettimeofday(&tv1, NULL);
141        for (i = 0; i < c; i++)
142            for (j = 0; j < sz/4; j++)
143                foo = b[j];
144
145        gettimeofday(&tv2, NULL);
146
147        tv_sub(&tv2, &tv1);
148
149        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));
150    }
151    return 0;
152}
153
154struct {
155    char *name;
156    int (*ptr)(int);
157} function_table[]  = {
158    {"sleep", do_sleep},
159    {"cpu", do_cpu},
160    {"memset", do_memset},
161    {"memcpy", do_memcpy},
162    {"memread", do_memread},
163    {NULL, NULL},
164};
165
166static void usage() {
167    int i;
168
169    printf("Usage:\n");
170    for (i = 0; function_table[i].name; i++) {
171        printf("\tmicro_bench %s ARG\n", function_table[i].name);
172    }
173}
174
175int main(int argc, char **argv) {
176    int i;
177
178    if (argc != 3) {
179        usage();
180        return -1;
181    }
182    for (i = 0; function_table[i].name; i++) {
183        if (!strcmp(argv[1], function_table[i].name)) {
184            printf("%s\n", function_table[i].name);
185            return (*function_table[i].ptr)(atoi(argv[2]));
186        }
187    }
188    usage();
189    return -1;
190}
191