summaryrefslogtreecommitdiff
path: root/micro_bench
diff options
context:
space:
mode:
authorNick Pelly <npelly@google.com>2010-08-26 11:21:29 -0700
committerNick Pelly <npelly@google.com>2010-08-26 11:21:29 -0700
commit6ca26ef8a78cc46dd8c779dcd7c611a247dd22c7 (patch)
tree46642bc71242669bab8d2f3645f27123ff57deae /micro_bench
parent7ee0b1a6ed0c09e6bf2ff9b2311267df6f201a0a (diff)
downloadextras-6ca26ef8a78cc46dd8c779dcd7c611a247dd22c7.tar.gz
Add a couple of performance debug utilities.
micro_bench provides very simple tests for o sleep accuracy o cpu o memcpy o memset sane_schedstat is a front-end for /proc/schedstat to diff and format the counters. Change-Id: I6e178fe37fcfc9bf0a83ec17852e31146a91e7a4 Signed-off-by: Nick Pelly <npelly@google.com>
Diffstat (limited to 'micro_bench')
-rw-r--r--micro_bench/Android.mk10
-rw-r--r--micro_bench/micro_bench.c188
2 files changed, 198 insertions, 0 deletions
diff --git a/micro_bench/Android.mk b/micro_bench/Android.mk
new file mode 100644
index 00000000..0e819c37
--- /dev/null
+++ b/micro_bench/Android.mk
@@ -0,0 +1,10 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := micro_bench.c
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
+LOCAL_MODULE_TAGS := debug
+LOCAL_MODULE := micro_bench
+
+include $(BUILD_EXECUTABLE)
diff --git a/micro_bench/micro_bench.c b/micro_bench/micro_bench.c
new file mode 100644
index 00000000..c67a52fa
--- /dev/null
+++ b/micro_bench/micro_bench.c
@@ -0,0 +1,188 @@
+/*
+** 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>
+
+/* 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 delay) {
+ struct timeval tv1;
+ struct timeval tv2;
+
+ while (1) {
+ 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 a) {
+ struct timeval tv1;
+ struct timeval tv2;
+
+ while (1) {
+ 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 sz) {
+ struct timeval tv1;
+ struct timeval tv2;
+ int i;
+
+ uint8_t *b = malloc(sz);
+ if (!b) return -1;
+ int c = 1000000000/sz;
+
+ while (1) {
+ gettimeofday(&tv1, NULL);
+ for (i = 0; i < c; i++)
+ 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 sz) {
+ struct timeval tv1;
+ struct timeval tv2;
+ int i;
+
+ uint8_t *a = malloc(sz);
+ if (!a) return -1;
+ uint8_t *b = malloc(sz);
+ if (!b) return -1;
+ int c = 1000000000/sz;
+
+ while (1) {
+ gettimeofday(&tv1, NULL);
+ for (i = 0; i < c; i++)
+ 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 sz) {
+ struct timeval tv1;
+ struct timeval tv2;
+ int i, j;
+
+ int *b = malloc(sz);
+ if (!b) return -1;
+ int c = 1000000000/sz;
+
+ while (1) {
+ gettimeofday(&tv1, NULL);
+ for (i = 0; i < c; i++)
+ for (j = 0; j < sz/4; j++)
+ foo = b[j];
+
+ 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);
+} 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\n", function_table[i].name);
+ }
+}
+
+int main(int argc, char **argv) {
+ int i;
+
+ if (argc != 3) {
+ usage();
+ return -1;
+ }
+ 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)(atoi(argv[2]));
+ }
+ }
+ usage();
+ return -1;
+}