summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2011-03-19 22:28:32 -0400
committerRich Felker <dalias@aerifal.cx>2011-03-19 22:28:32 -0400
commit0346d5174eb0ce553cda977d91dd6cf61b7ffe82 (patch)
tree339d9665b997e2c0b8f60fc1c52680635108f86a
downloadlibc-bench-0346d5174eb0ce553cda977d91dd6cf61b7ffe82.tar.gz
initial check-in
-rw-r--r--Makefile22
-rw-r--r--main.c98
-rw-r--r--malloc.c154
-rw-r--r--pthread.c97
-rw-r--r--regex.c30
-rw-r--r--stdio.c35
-rw-r--r--string.c68
-rw-r--r--utf8.c80
8 files changed, 584 insertions, 0 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..7769ef5
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,22 @@
+
+SRCS = $(sort $(wildcard *.c))
+OBJS = $(SRCS:.c=.o)
+
+CFLAGS = -Os -D_XOPEN_SOURCE=700
+LDFLAGS = -static
+LIBS = -lpthread -lrt -lpthread
+
+
+all: libc-bench
+
+clean:
+ rm -f $(OBJS) libc-bench
+
+test: all
+ ./libc-bench
+
+libc-bench: $(OBJS)
+ $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
+
+%.o: %.c
+ $(CC) $(CFLAGS) -c -o $@ $<
diff --git a/main.c b/main.c
new file mode 100644
index 0000000..12bb541
--- /dev/null
+++ b/main.c
@@ -0,0 +1,98 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/wait.h>
+
+void print_stats(struct timespec tv0)
+{
+ FILE *f;
+ char buf[256];
+ struct timespec tv;
+ int maj, min, in_heap=0;
+ unsigned long l;
+ size_t vm_size=0, vm_rss=0, vm_priv_dirty=0;
+
+ clock_gettime(CLOCK_REALTIME, &tv);
+ tv.tv_sec -= tv0.tv_sec;
+ if ((tv.tv_nsec -= tv0.tv_nsec) < 0) {
+ tv.tv_nsec += 1000000000;
+ tv.tv_sec--;
+ }
+
+ f = fopen("/proc/self/smaps", "rb");
+ if (f) while (fgets(buf, sizeof buf, f)) {
+ if (sscanf(buf, "%*lx-%*lx %*s %*lx %x:%x %*lu %*s", &maj, &min)==2)
+ in_heap = (!maj && !min && !strstr(buf, "---p") && (strstr(buf, "[heap]") || !strchr(buf, '[')));
+ if (in_heap) {
+ if (sscanf(buf, "Size: %lu", &l)==1) vm_size += l;
+ else if (sscanf(buf, "Rss: %lu", &l)==1) vm_rss += l;
+ else if (sscanf(buf, "Private_Dirty: %lu", &l)==1) vm_priv_dirty += l;
+ }
+ }
+ if (f) fclose(f);
+ printf(" time: %ld.%.9ld, virt: %zu, res: %zu, dirty: %zu\n\n",
+ (long)tv.tv_sec, (long)tv.tv_nsec,
+ vm_size, vm_rss, vm_priv_dirty);
+}
+
+int run_bench(const char *label, size_t (*bench)(void *), void *params)
+{
+ struct timespec tv0;
+ pid_t p = fork();
+ if (p) {
+ int status;
+ wait(&status);
+ return status;
+ }
+
+ puts(label);
+ clock_gettime(CLOCK_REALTIME, &tv0);
+ bench(params);
+ print_stats(tv0);
+ exit(0);
+}
+
+#define RUN(a, b) \
+ extern size_t (a)(void *); \
+ run_bench(#a " (" #b ")", (a), (b))
+
+int main()
+{
+ RUN(b_malloc_sparse, 0);
+ RUN(b_malloc_bubble, 0);
+ RUN(b_malloc_tiny1, 0);
+ RUN(b_malloc_tiny2, 0);
+ RUN(b_malloc_big1, 0);
+ RUN(b_malloc_big2, 0);
+ RUN(b_malloc_thread_stress, 0);
+ RUN(b_malloc_thread_local, 0);
+
+ RUN(b_string_strstr, "abcdefghijklmnopqrstuvwxyz");
+ RUN(b_string_strstr, "azbycxdwevfugthsirjqkplomn");
+ RUN(b_string_strstr, "aaaaaaaaaaaaaacccccccccccc");
+ RUN(b_string_strstr, "aaaaaaaaaaaaaaaaaaaaaaaaac");
+ RUN(b_string_strstr, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaac");
+ RUN(b_string_memset, 0);
+ RUN(b_string_strchr, 0);
+ RUN(b_string_strlen, 0);
+
+ RUN(b_pthread_createjoin_serial1, 0);
+ RUN(b_pthread_createjoin_serial2, 0);
+ RUN(b_pthread_create_serial1, 0);
+ RUN(b_pthread_uselesslock, 0);
+ RUN(b_pthread_createjoin_minimal1, 0);
+ RUN(b_pthread_createjoin_minimal2, 0);
+
+ RUN(b_utf8_bigbuf, 0);
+ RUN(b_utf8_onebyone, 0);
+
+ RUN(b_stdio_putcgetc, 0);
+ RUN(b_stdio_putcgetc_unlocked, 0);
+
+ RUN(b_regex_compile, "(a|b|c)*d*b");
+ RUN(b_regex_search, "(a|b|c)*d*b");
+ RUN(b_regex_search, "a{25}b");
+}
+
diff --git a/malloc.c b/malloc.c
new file mode 100644
index 0000000..79cc88b
--- /dev/null
+++ b/malloc.c
@@ -0,0 +1,154 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pthread.h>
+
+size_t b_malloc_sparse(void *dummy)
+{
+ void *p[10000];
+ size_t i;
+ for (i=0; i<sizeof p/sizeof *p; i++) {
+ p[i] = malloc(4000);
+ memset(p[i], 0, 4000);
+ }
+ for (i=0; i<sizeof p/sizeof *p; i++)
+ if (i%150) free(p[i]);
+ return 0;
+}
+
+size_t b_malloc_bubble(void *dummy)
+{
+ void *p[10000];
+ size_t i;
+ for (i=0; i<sizeof p/sizeof *p; i++) {
+ p[i] = malloc(4000);
+ memset(p[i], 0, 4000);
+ }
+ for (i=0; i<sizeof p/sizeof *p-1; i++)
+ free(p[i]);
+ return 0;
+}
+
+size_t b_malloc_tiny1(void *dummy)
+{
+ void *p[10000];
+ size_t i;
+ for (i=0; i<sizeof p/sizeof *p; i++) {
+ p[i] = malloc((i%4+1)*16);
+ }
+ for (i=0; i<sizeof p/sizeof *p; i++) {
+ free(p[i]);
+ }
+ return 0;
+}
+
+size_t b_malloc_tiny2(void *dummy)
+{
+ void *p[10000];
+ size_t i;
+ for (i=0; i<sizeof p/sizeof *p; i++) {
+ p[i] = malloc((i%4+1)*16);
+ }
+ for (i=1; i; i = (i+57)%(sizeof p/sizeof *p))
+ free(p[i]);
+ return 0;
+}
+
+size_t b_malloc_big1(void *dummy)
+{
+ void *p[2000];
+ size_t i;
+ for (i=0; i<sizeof p/sizeof *p; i++) {
+ p[i] = malloc((i%4+1)*16384);
+ }
+ for (i=0; i<sizeof p/sizeof *p; i++) {
+ free(p[i]);
+ }
+ return 0;
+}
+
+size_t b_malloc_big2(void *dummy)
+{
+ void *p[2000];
+ size_t i;
+ for (i=0; i<sizeof p/sizeof *p; i++) {
+ p[i] = malloc((i%4+1)*16384);
+ }
+ for (i=1; i; i = (i+57)%(sizeof p/sizeof *p))
+ free(p[i]);
+ return 0;
+}
+
+
+#define LOOPS 100000
+#define SH_COUNT 300
+#define PV_COUNT 300
+#define MAX_SZ 500
+#define DEF_SZ 40
+
+struct foo {
+ pthread_mutex_t lock;
+ void *mem;
+};
+
+static unsigned rng(unsigned *r)
+{
+ return *r = *r * 1103515245 + 12345;
+}
+
+
+static void *stress(void *arg)
+{
+ struct foo *foo = arg;
+ unsigned r = (unsigned)pthread_self();
+ int i, j;
+ size_t sz;
+ void *p;
+
+ for (i=0; i<LOOPS; i++) {
+ j = rng(&r) % SH_COUNT;
+ sz = rng(&r) % MAX_SZ;
+ pthread_mutex_lock(&foo[j].lock);
+ p = foo[j].mem;
+ foo[j].mem = 0;
+ pthread_mutex_unlock(&foo[j].lock);
+ free(p);
+ if (!p) {
+ p = malloc(sz);
+ pthread_mutex_lock(&foo[j].lock);
+ if (!foo[j].mem) foo[j].mem = p, p = 0;
+ pthread_mutex_unlock(&foo[j].lock);
+ free(p);
+ }
+ }
+ return 0;
+}
+
+size_t b_malloc_thread_stress(void *dummy)
+{
+ struct foo foo[SH_COUNT] = {0};
+ pthread_t td1, td2;
+ void *res;
+ int i;
+
+ pthread_create(&td1, 0, stress, foo);
+ pthread_create(&td2, 0, stress, foo);
+ pthread_join(td1, &res);
+ pthread_join(td2, &res);
+ return 0;
+}
+
+size_t b_malloc_thread_local(void *dummy)
+{
+ struct foo foo1[SH_COUNT] = {0};
+ struct foo foo2[SH_COUNT] = {0};
+ pthread_t td1, td2;
+ void *res;
+ int i;
+
+ pthread_create(&td1, 0, stress, foo1);
+ pthread_create(&td2, 0, stress, foo2);
+ pthread_join(td1, &res);
+ pthread_join(td2, &res);
+ return 0;
+}
diff --git a/pthread.c b/pthread.c
new file mode 100644
index 0000000..33ab9ec
--- /dev/null
+++ b/pthread.c
@@ -0,0 +1,97 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pthread.h>
+#include <unistd.h>
+
+void *emptyfunc(void *dummy)
+{
+ return 0;
+}
+
+size_t b_pthread_createjoin_serial1(void *dummy)
+{
+ size_t i;
+ pthread_t td;
+ for (i=0; i<2500; i++) {
+ pthread_create(&td, 0, emptyfunc, 0);
+ pthread_join(td, &dummy);
+ }
+ return 0;
+}
+
+size_t b_pthread_createjoin_serial2(void *dummy)
+{
+ size_t i, j;
+ pthread_t td[50];
+ for (j=0; j<50; j++) {
+ for (i=0; i<sizeof td/sizeof *td; i++)
+ pthread_create(td+i, 0, emptyfunc, 0);
+ for (i=0; i<sizeof td/sizeof *td; i++)
+ pthread_join(td[i], &dummy);
+ }
+ return 0;
+}
+
+size_t b_pthread_create_serial1(void *dummy)
+{
+ size_t i;
+ pthread_attr_t attr;
+ pthread_t td;
+ pthread_attr_init(&attr);
+ pthread_attr_setstacksize(&attr, 16384);
+ for (i=0; i<2500; i++)
+ pthread_create(&td, &attr, emptyfunc, 0);
+ return 0;
+}
+
+void *lockunlock(void *mut)
+{
+ size_t i;
+ for (i=0; i<1000000; i++) {
+ pthread_mutex_lock(mut);
+ pthread_mutex_unlock(mut);
+ }
+ return 0;
+}
+
+size_t b_pthread_uselesslock(void *dummy)
+{
+ pthread_t td;
+ pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
+ pthread_create(&td, 0, lockunlock, &mut);
+ pthread_join(td, &dummy);
+ return 0;
+}
+
+size_t b_pthread_createjoin_minimal1(void *dummy)
+{
+ size_t i;
+ pthread_t td;
+ pthread_attr_t a;
+ pthread_attr_init(&a);
+ pthread_attr_setstacksize(&a, sysconf(_SC_PAGESIZE));
+ pthread_attr_setguardsize(&a, 0);
+ for (i=0; i<2500; i++) {
+ pthread_create(&td, &a, emptyfunc, 0);
+ pthread_join(td, &dummy);
+ }
+ return 0;
+}
+
+size_t b_pthread_createjoin_minimal2(void *dummy)
+{
+ size_t i, j;
+ pthread_t td[50];
+ pthread_attr_t a;
+ pthread_attr_init(&a);
+ pthread_attr_setstacksize(&a, sysconf(_SC_PAGESIZE));
+ pthread_attr_setguardsize(&a, 0);
+ for (j=0; j<50; j++) {
+ for (i=0; i<sizeof td/sizeof *td; i++)
+ pthread_create(td+i, &a, emptyfunc, 0);
+ for (i=0; i<sizeof td/sizeof *td; i++)
+ pthread_join(td[i], &dummy);
+ }
+ return 0;
+}
diff --git a/regex.c b/regex.c
new file mode 100644
index 0000000..46cfe37
--- /dev/null
+++ b/regex.c
@@ -0,0 +1,30 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <regex.h>
+#include <locale.h>
+
+size_t b_regex_compile(void *s)
+{
+ regex_t re;
+ size_t i;
+ setlocale(LC_CTYPE, "");
+ for (i=0; i<1000; i++) {
+ regcomp(&re, s, REG_EXTENDED);
+ regfree(&re);
+ }
+}
+
+size_t b_regex_search(void *s)
+{
+ char buf[260000];
+ regex_t re;
+ size_t i;
+ setlocale(LC_CTYPE, "");
+ memset(buf, 'a', sizeof(buf)-2);
+ buf[sizeof buf - 2] = 'b';
+ buf[sizeof buf - 1] = 0;
+ regcomp(&re, s, REG_EXTENDED);
+ regexec(&re, buf, 0, 0, 0);
+ regfree(&re);
+}
diff --git a/stdio.c b/stdio.c
new file mode 100644
index 0000000..0d41f86
--- /dev/null
+++ b/stdio.c
@@ -0,0 +1,35 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+size_t b_stdio_putcgetc(void *dummy)
+{
+ FILE *f = tmpfile();
+ size_t i;
+ size_t cs;
+
+ for (i=0; i<5000000; i++)
+ putc('x', f);
+ fseeko(f, 0, SEEK_SET);
+ for (i=0; i<5000000; i++)
+ cs += getc(f);
+ fclose(f);
+
+ return cs;
+}
+
+size_t b_stdio_putcgetc_unlocked(void *dummy)
+{
+ FILE *f = tmpfile();
+ size_t i;
+ size_t cs;
+
+ for (i=0; i<5000000; i++)
+ putc_unlocked('x', f);
+ fseeko(f, 0, SEEK_SET);
+ for (i=0; i<5000000; i++)
+ cs += getc_unlocked(f);
+ fclose(f);
+
+ return cs;
+}
diff --git a/string.c b/string.c
new file mode 100644
index 0000000..158b828
--- /dev/null
+++ b/string.c
@@ -0,0 +1,68 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define BUFLEN 500000
+
+size_t b_string_strstr(void *dummy)
+{
+ const char *needle = dummy;
+ size_t l = strlen(needle);
+ size_t i;
+ size_t cnt = 10000;
+ size_t cs = 0;
+ char *haystack = malloc(l * cnt + 1);
+ for (i=0; i<cnt-1; i++) {
+ memcpy(haystack + l*i, needle, l);
+ haystack[l*i+l-1] ^= 1;
+ }
+ memcpy(haystack + l*i, needle, l+1);
+ for (i=0; i<50; i++) {
+ haystack[0]^=1;
+ cs += (int)strstr(haystack, needle);
+ }
+ free(haystack);
+ return cs;
+}
+
+size_t b_string_memset(void *dummy)
+{
+ char *buf = malloc(BUFLEN);
+ size_t i;
+ for (i=0; i<100; i++)
+ memset(buf+i, i, BUFLEN-i);
+ free(buf);
+ return 0;
+}
+
+size_t b_string_strchr(void *dummy)
+{
+ char *buf = malloc(BUFLEN);
+ size_t i;
+ size_t cs;
+ memset(buf, 'a', BUFLEN);
+ buf[BUFLEN-1] = 0;
+ buf[BUFLEN-2] = 'b';
+ for (i=0; i<100; i++) {
+ buf[i] = '0'+i%8;
+ cs += (int)strchr(buf, 'b');
+ }
+ free(buf);
+ return cs;
+}
+
+size_t b_string_strlen(void *dummy)
+{
+ char *buf = malloc(BUFLEN);
+ size_t i;
+ size_t cs = 0;
+
+ memset(buf, 'a', BUFLEN-1);
+ buf[BUFLEN-1] = 0;
+ for (i=0; i<100; i++) {
+ buf[i] = '0'+i%8;
+ cs += strlen(buf);
+ }
+ free(buf);
+ return cs;
+}
diff --git a/utf8.c b/utf8.c
new file mode 100644
index 0000000..5a675ed
--- /dev/null
+++ b/utf8.c
@@ -0,0 +1,80 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <locale.h>
+#include <langinfo.h>
+
+size_t b_utf8_bigbuf(void *dummy)
+{
+ char *buf;
+ wchar_t *wbuf;
+ size_t i, j, k, l;
+ size_t cs;
+
+ setlocale(LC_CTYPE, "C.UTF-8")
+ || setlocale(LC_CTYPE, "en_US.UTF-8")
+ || setlocale(LC_CTYPE, "en_GB.UTF-8")
+ || setlocale(LC_CTYPE, "en.UTF-8")
+ || setlocale(LC_CTYPE, "de_DE-8")
+ || setlocale(LC_CTYPE, "fr_FR-8");
+ if (strcmp(nl_langinfo(CODESET), "UTF-8")) return -1;
+
+ buf = malloc(500000);
+ wbuf = malloc(500000*sizeof(wchar_t));
+ l = 0;
+ for (i=0xc3; i<0xe0; i++)
+ for (j=0x80; j<0xc0; j++)
+ buf[l++] = i, buf[l++] = j;
+ for (i=0xe1; i<0xed; i++)
+ for (j=0x80; j<0xc0; j++)
+ for (k=0x80; k<0xc0; k++)
+ buf[l++] = i, buf[l++] = j, buf[l++] = k;
+ for (i=0xf1; i<0xf4; i++)
+ for (j=0x80; j<0xc0; j++)
+ for (k=0x80; k<0xc0; k++)
+ buf[l++] = i, buf[l++] = j, buf[l++] = 0x80, buf[l++] = k;
+ buf[l++] = 0;
+ for (i=0; i<50; i++)
+ cs += mbstowcs(wbuf, buf, 500000);
+ free(wbuf);
+ free(buf);
+ return cs;
+}
+
+size_t b_utf8_onebyone(void *dummy)
+{
+ char *buf;
+ wchar_t wc;
+ size_t i, j, k, l;
+ size_t cs;
+ mbstate_t st = {0};
+
+ setlocale(LC_CTYPE, "C.UTF-8")
+ || setlocale(LC_CTYPE, "en_US.UTF-8")
+ || setlocale(LC_CTYPE, "en_GB.UTF-8")
+ || setlocale(LC_CTYPE, "en.UTF-8")
+ || setlocale(LC_CTYPE, "de_DE-8")
+ || setlocale(LC_CTYPE, "fr_FR-8");
+ if (strcmp(nl_langinfo(CODESET), "UTF-8")) return -1;
+
+ buf = malloc(500000);
+ l = 0;
+ for (i=0xc3; i<0xe0; i++)
+ for (j=0x80; j<0xc0; j++)
+ buf[l++] = i, buf[l++] = j;
+ for (i=0xe1; i<0xed; i++)
+ for (j=0x80; j<0xc0; j++)
+ for (k=0x80; k<0xc0; k++)
+ buf[l++] = i, buf[l++] = j, buf[l++] = k;
+ for (i=0xf1; i<0xf4; i++)
+ for (j=0x80; j<0xc0; j++)
+ for (k=0x80; k<0xc0; k++)
+ buf[l++] = i, buf[l++] = j, buf[l++] = 0x80, buf[l++] = k;
+ buf[l++] = 0;
+ for (i=0; i<50; i++) {
+ for (j=0; buf[j]; j+=mbrtowc(&wc, buf+j, 4, &st));
+ }
+ free(buf);
+ return cs;
+}