diff --git a/Makefile b/Makefile index 05e3145..617e5c5 100644 --- a/Makefile +++ b/Makefile @@ -1,12 +1,12 @@ CC = 9c LD = 9l -CFLAGS = -Wall -Wextra -O2 +CFLAGS = -Wall -Wextra -O2 -g PROG = strans SRCS = $(wildcard *.c) OBJS = $(SRCS:.c=.o) -all: $(PROG) +all: $(PROG) xim bench $(PROG): $(OBJS) $(LD) -o $@ $(OBJS) -lthread -lString -lbio -lxcb -lm @@ -15,5 +15,13 @@ $(OBJS): dat.h fn.h ipc.h clean: rm -f $(OBJS) $(PROG) + make -C xim/ clean + make -C bench/ clean -.PHONY: all clean +xim: + make -C xim/ + +bench: + make -C bench/ + +.PHONY: all clean xim bench diff --git a/bench.sh b/bench.sh new file mode 100755 index 0000000..c19a01a --- /dev/null +++ b/bench.sh @@ -0,0 +1,23 @@ +#!/bin/sh + +pkill strans +pkill strans-xim +sleep 1 + +./strans map font & +sleep 1 + +# warm up glyph cache +./bench/bench bench/bench.keys 100 +echo "cache warmed up" + +STRANS_PID=$(pgrep -x strans) +perf record -g -o bench/perf.data -p "$STRANS_PID" & +PERF_PID=$! +sleep 1 + +./bench/bench bench/bench.keys 100 + +kill -INT $PERF_PID +wait $PERF_PID 2>/dev/null +pkill strans diff --git a/bench/Makefile b/bench/Makefile new file mode 100644 index 0000000..e9ff193 --- /dev/null +++ b/bench/Makefile @@ -0,0 +1,8 @@ +CC = cc +CFLAGS = -Wall -O2 + +bench: main.c + $(CC) $(CFLAGS) -o $@ main.c + +clean: + rm -f bench diff --git a/bench/bench b/bench/bench new file mode 100755 index 0000000..634ccef Binary files /dev/null and b/bench/bench differ diff --git a/bench/bench.keys b/bench/bench.keys new file mode 100644 index 0000000..bf6f4b7 --- /dev/null +++ b/bench/bench.keys @@ -0,0 +1,30 @@ +^ntoukyounotenki^Ryoidesu^R +konpyuutanopuroguramu^B^B^Bgramu^R +nihongowobenkyoushiteimasu^R +sakuranoshanohana^B^B^B^Bhanagasaiteiru^R +kaigi^Ekyounokaigi^R +ashitahaiitenkininarudeshou^R +^sdkssudgktpdy^Rgksrmfekfqnxm^R +vmfhrrh^Btprtmxm^Rdufrlavldml^R +dmlrlwkekfwprtm^R +gksrnl^B^B^Bdlfp^R +answkd^Eanswkd^R +qkrtlwkf^B^B^Bwkfgkf^R +^thello world^R +the quick brown fox jumps over the lazy dog^R +programming is fun^R +^vVietNam^Rxinchaobancokhoekhong^R +toidilambaitap^B^B^Bbaitap^R +hoctiengviet^R +^nkaishanitsuutomeshiteimasu^R +tanaboraguukoudesu^B^B^B^B^Bkoudesu^R +^srhksrnrdlTkfgkwl^R +answkddkssud^B^Bdkssud^R +wnsdydgktpdy^R +^vtoidenlopcuahang^R +motngaymoiconduong^R +^thigh performance input method^R +^nnyuuryokuhouhou^R +tesutonosuuretsu^R +^sxkfldzmsdml^R +qhfmfjxm^R diff --git a/bench/main.c b/bench/main.c new file mode 100644 index 0000000..f180dba --- /dev/null +++ b/bench/main.c @@ -0,0 +1,168 @@ +#include +#include +#include +#include +#include +#include +#include + +enum { + Kback = 0xf008, + Kret = 0xf00d, + Kesc = 0xf01b, + Mctrl = 1<<2, +}; + +typedef struct Key Key; +struct Key { + int k; + int mod; +}; + +static Key *keys; +static int nkeys; +static int fd; + +static void +die(char *msg) +{ + perror(msg); + exit(1); +} + +static void +addkey(int k, int mod) +{ + static int cap; + + if(nkeys >= cap){ + cap = cap ? cap * 2 : 256; + keys = realloc(keys, cap * sizeof(Key)); + if(!keys) + die("realloc"); + } + keys[nkeys].k = k; + keys[nkeys].mod = mod; + nkeys++; +} + +static void +loadkeys(char *file) +{ + FILE *f; + int c; + + f = fopen(file, "r"); + if(!f) + die(file); + while((c = fgetc(f)) != EOF){ + if(c == '\n' || c == '\r') + continue; + if(c != '^'){ + addkey(c, 0); + continue; + } + c = fgetc(f); + if(c == EOF) + break; + switch(c){ + case 'B': + addkey(Kback, 0); + break; + case 'R': + addkey(Kret, 0); + break; + case 'E': + addkey(Kesc, 0); + break; + default: + addkey(c, Mctrl); + break; + } + } + fclose(f); +} + +static void +dial(void) +{ + struct sockaddr_un addr; + + fd = socket(AF_UNIX, SOCK_STREAM, 0); + if(fd < 0) + die("socket"); + memset(&addr, 0, sizeof(addr)); + addr.sun_family = AF_UNIX; + snprintf(addr.sun_path, sizeof(addr.sun_path), + "/tmp/strans.%d", getuid()); + if(connect(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) + die("connect"); +} + +static void +sendkey(int key, int mod) +{ + unsigned char req[4]; + + req[0] = 0; + req[1] = mod; + req[2] = key & 0xff; + req[3] = (key >> 8) & 0xff; + if(write(fd, req, 4) != 4) + die("write"); +} + +static int +readresp(void) +{ + unsigned char buf[256]; + int n; + + if(read(fd, buf, 2) != 2) + return -1; + n = buf[1]; + if(n > 0 && read(fd, buf + 2, n) != n) + return -1; + return 0; +} + +static double +now(void) +{ + struct timespec ts; + + clock_gettime(CLOCK_MONOTONIC, &ts); + return ts.tv_sec + ts.tv_nsec * 1e-9; +} + +int +main(int argc, char **argv) +{ + int i, j, niter; + double t0, t1, dt; + + if(argc < 2){ + fprintf(stderr, "usage: bench file [niter]\n"); + exit(1); + } + + loadkeys(argv[1]); + niter = argc > 2 ? atoi(argv[2]) : 1000; + dial(); + t0 = now(); + for(i = 0; i < niter; i++) + for(j = 0; j < nkeys; j++){ + sendkey(keys[j].k, keys[j].mod); + if(readresp() < 0){ + fprintf(stderr, "failed at iter %d key %d\n", i, j); + exit(1); + } + } + t1 = now(); + dt = t1 - t0; + printf("%d iters x %d keys = %d keys\n", niter, nkeys, niter * nkeys); + printf("%.3f ms total, %.3f us/key, %.3f us/iter\n", + dt * 1000, dt * 1e6 / (niter * nkeys), dt * 1e6 / niter); + close(fd); + return 0; +} diff --git a/bench/perf.data b/bench/perf.data new file mode 100644 index 0000000..84a8914 Binary files /dev/null and b/bench/perf.data differ