Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 95 additions & 0 deletions user/apps/libc-bench/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
#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_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");
}
34 changes: 34 additions & 0 deletions user/apps/libc-bench/makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
ifeq ($(ARCH), x86_64)
CROSS_COMPILE=x86_64-linux-musl-
else ifeq ($(ARCH), riscv64)
CROSS_COMPILE=riscv64-linux-musl-
endif

SRCS = $(sort $(wildcard *.c))
OBJS = $(SRCS:.c=.o)

CC=$(CROSS_COMPILE)gcc

CFLAGS = -Os
LDFLAGS = -static
LIBS = -lpthread -lrt -lpthread

.PHONY: all clean test install


all: libc-bench

clean:
rm -f $(OBJS) libc-bench

test: all
./libc-bench

install: all
mv libc-bench $(DADK_CURRENT_BUILD_DIR)/libc-bench

libc-bench: $(OBJS)
$(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)

%.o: %.c
$(CC) $(CFLAGS) -c -o $@ $<
154 changes: 154 additions & 0 deletions user/apps/libc-bench/malloc.c
Original file line number Diff line number Diff line change
@@ -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;
}
64 changes: 64 additions & 0 deletions user/apps/libc-bench/pthread.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.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;
}
30 changes: 30 additions & 0 deletions user/apps/libc-bench/regex.c
Original file line number Diff line number Diff line change
@@ -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);
}
Loading
Loading