diff options
author | Rich Felker <dalias@aerifal.cx> | 2011-03-19 22:28:32 -0400 |
---|---|---|
committer | Rich Felker <dalias@aerifal.cx> | 2011-03-19 22:28:32 -0400 |
commit | 0346d5174eb0ce553cda977d91dd6cf61b7ffe82 (patch) | |
tree | 339d9665b997e2c0b8f60fc1c52680635108f86a | |
download | libc-bench-0346d5174eb0ce553cda977d91dd6cf61b7ffe82.tar.gz |
initial check-in
-rw-r--r-- | Makefile | 22 | ||||
-rw-r--r-- | main.c | 98 | ||||
-rw-r--r-- | malloc.c | 154 | ||||
-rw-r--r-- | pthread.c | 97 | ||||
-rw-r--r-- | regex.c | 30 | ||||
-rw-r--r-- | stdio.c | 35 | ||||
-rw-r--r-- | string.c | 68 | ||||
-rw-r--r-- | utf8.c | 80 |
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 $@ $< @@ -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; +} @@ -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); +} @@ -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; +} @@ -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; +} |