C++程序  |  202行  |  4.66 KB

/*
** 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 <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <sys/uio.h>
#include <unistd.h>
#include <sys/time.h>
#include <stdint.h>
#include <string.h>

/* 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;
}