Browse files

eval: minor optimizations

  • Loading branch information...
hellerve committed Nov 16, 2018
1 parent 2954d32 commit fb8b05158514bd2d37a1a89247d3bcbd0b6e3d03
Showing with 35 additions and 7 deletions.
  1. +12 −1 Makefile
  2. +5 −2
  3. +18 −4 src/eval.c
@@ -3,14 +3,25 @@ BUILDDIR=bin/
SOURCES=$(wildcard src/*.c)
override CFLAGS+=-Werror -Wall -g -fPIC -DNDEBUG -Wfloat-equal -Wundef -Wwrite-strings -Wuninitialized -pedantic -std=c11 -O2 -Wno-gnu
override CFLAGS+=-std=c11 -O2 -Wno-gnu
DEVFLAGS=-Werror -Wall -g -fPIC -DNDEBUG -Wfloat-equal -Wundef -Wwrite-strings -Wuninitialized -pedantic

all: main.c
mkdir -p $(BUILDDIR)

no_wrap: main.c

dev: main.c
mkdir -p $(BUILDDIR)

install: all

rm -rf $(PREFIX)$(TARGET)

rm -rf $(BUILDDIR)
@@ -52,8 +52,11 @@ a newline to make it pretty.
## Implementation

Actors are implemented as pthreads. The virtual machine is a simple direct
threaded bytecode VM that offers 30,000 elements to each Brainfuck program (it
will wrap around if you go past the low or high threshold).
threaded bytecode VM that offers 30,000 elements to each Brainfuck program. It
will wrap around if you go past the low or high threshold—this can be turned
off by passing `-DNO_WRAP` to the compiler or calling `make no_wrap`, as
disabling it might buy you a little bit of performance, depending on your

It should be reasonably performant, but who cares? I hope noone’s going to run
their MapReduce jobs on it. There are some low-hanging fruits for optimization,
@@ -17,7 +17,7 @@ typedef struct {
} actor_ctx;

We’re using direct threadin here. Basically, we avoid looping and case
We’re using direct threading here. Basically, we avoid looping and case
dispatch by using a computed GOTO instead. This comes at the cost of using a
GNU extension, but I love those anyway.
@@ -39,8 +39,13 @@ void* eval(void* arg) {
do_zero: t[h] = 0; DISPATCH();
do_inc: t[h]++; DISPATCH();
do_dec: t[h]--; DISPATCH();
do_fwd: h = h < TAPE_LEN-1 ? h+1 : 0; DISPATCH();
do_bck: h = h > -1 ? h-1 : TAPE_LEN-1; DISPATCH();
#ifdef NO_WRAP
do_fwd: h++; DISPATCH();
do_bck: h--; DISPATCH();
do_fwd: h = h+1 % TAPE_LEN; DISPATCH();
do_bck: h = h-1 % TAPE_LEN; DISPATCH();
do_prn: printf("%c", t[h]); DISPATCH();
do_read: scanf("%c", (char*)&t[h]); DISPATCH();
do_startl: if(!t[h]) i = c.arg; DISPATCH();
@@ -103,10 +108,19 @@ void eval_actors(actors* ac) {
ctx.code = ac->code[i];
ctxs[i] = ctx;
pthread_create(&ts[i], NULL, eval, &ctxs[i]);
if(ac->num == 1) {
// if we just have one thread, we eval it directly; buys us about 2% perf
} else {
pthread_create(&ts[i], NULL, eval, &ctxs[i]);
down = ctx.up;
down_written = ctx.up_written;

for (i = 0; i < ac->num; i++) {
pthread_join(ts[i], NULL);
actor_ctx ctx = ctxs[i];

0 comments on commit fb8b051

Please sign in to comment.