From c97d443e62bd27755fa62e3f5dc8836c80ae5fc7 Mon Sep 17 00:00:00 2001 From: John Hawthorn Date: Sun, 20 Dec 2009 09:18:48 -0800 Subject: add performance tests for scaling. --- Makefile | 16 +++++++++++++--- src/meh.h | 6 ++++++ src/scale.c | 34 ++++++++++++++++----------------- src/xlib.c | 5 +---- test/test.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ test/test.h | 6 ++++++ 6 files changed, 104 insertions(+), 25 deletions(-) create mode 100644 test/test.c create mode 100644 test/test.h diff --git a/Makefile b/Makefile index d2e183b..4455b14 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,12 @@ +TARGET := meh +TESTTARGET := test/test + SRCFILES := $(wildcard src/*.c) OBJFILES := $(SRCFILES:%.c=%.o) DEPFILES := $(OBJFILES:%.o=%.d) -CLEANFILES := $(CLEANFILES) $(DEPFILES) $(OBJFILES) meh +TESTCLEAN := $(TESTTARGET) $(TESTTARGET).d $(TESTTARGET).o +CLEANFILES := $(CLEANFILES) $(DEPFILES) $(OBJFILES) test/test.o test/test.d test/test $(TARGET) LIBS ?= -lX11 -lXext -ljpeg -lpng -lgif PREFIX ?= /usr/local BINDIR = $(PREFIX)/bin @@ -14,7 +18,13 @@ CONFIG ?= ../config CFLAGS ?= -O3 -DNDEBUG meh: $(OBJFILES) - $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJFILES) $(LIBS) + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS) + +test: $(TESTTARGET) + ./$(TESTTARGET) + +test/test: test/test.o $(filter-out src/main.o, $(OBJFILES)) + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS) -include $(DEPFILES) @@ -28,5 +38,5 @@ install: clean: $(RM) $(CLEANFILES) -.PHONY: clean +.PHONY: clean test diff --git a/src/meh.h b/src/meh.h index 4333f51..f2d5e3c 100644 --- a/src/meh.h +++ b/src/meh.h @@ -31,6 +31,12 @@ struct image{ XImage *ximg; }; + +/* scale */ +void scale(struct image *img, int width, int height, int bytesperline, char* __restrict__ newBuf); +void nearestscale(struct image *img, int width, int height, int bytesperline, char* __restrict__ newBuf); + +/* XLib */ void setaspect(unsigned int w, unsigned int h); void xinit(); void drawimage(XImage *ximg, unsigned int width, unsigned int height); diff --git a/src/scale.c b/src/scale.c index 4cd62f3..21fa505 100644 --- a/src/scale.c +++ b/src/scale.c @@ -16,7 +16,7 @@ ) * (v)) >> 20) #define XLOOP(F) \ - for(x = 0; x < ximg->width*4;){ \ + for(x = 0; x < width*4;){ \ const unsigned int x0 = a[x++];\ const unsigned int x1 = a[x++];\ const unsigned int u = a[x++];\ @@ -28,29 +28,28 @@ } #define YITER \ - const unsigned int bufy = (y << 10) * img->bufheight / ximg->height;\ + const unsigned int bufy = (y << 10) * img->bufheight / height;\ const unsigned int v = (bufy & 1023);\ const unsigned int vr = 1023^v;\ - ibuf = &img->buf[y * img->bufheight / ximg->height * img->bufwidth * 3];\ + ibuf = &img->buf[y * img->bufheight / height * img->bufwidth * 3];\ ibufn = ibuf + dy; -void scale(struct image *img, XImage *ximg){ +void scale(struct image *img, int width, int height, int bytesperline, char* __restrict__ newBuf){ int x, y; const unsigned char * __restrict__ ibuf; const unsigned char * __restrict__ ibufn; const unsigned char * const bufend = &img->buf[img->bufwidth * img->bufheight * 3]; - char* __restrict__ newBuf = ximg->data; - const unsigned int jdy = ximg->bytes_per_line / 4 - ximg->width; + const unsigned int jdy = bytesperline / 4 - width; const unsigned int dy = img->bufwidth * 3; TDEBUG_START - unsigned int a[ximg->width * 4]; + unsigned int a[width * 4]; { - unsigned int dx = (img->bufwidth << 10) / ximg->width; - unsigned int bufx = img->bufwidth / ximg->width; - for(x = 0; x < ximg->width * 4;){ + unsigned int dx = (img->bufwidth << 10) / width; + unsigned int bufx = img->bufwidth / width; + for(x = 0; x < width * 4;){ if((bufx >> 10) >= img->bufwidth - 1){ a[x++] = (img->bufwidth - 1) * 3; a[x++] = (img->bufwidth - 1) * 3; @@ -90,20 +89,19 @@ void scale(struct image *img, XImage *ximg){ TDEBUG_END("scale") } -void linearscale(struct image *img, XImage *ximg){ +void nearestscale(struct image *img, int width, int height, int bytesperline, char* __restrict__ newBuf){ int x, y; unsigned char * __restrict__ ibuf; - char* __restrict__ newBuf = ximg->data; - unsigned int jdy = ximg->bytes_per_line / 4 - ximg->width; - unsigned int dx = (img->bufwidth << 10) / ximg->width; + unsigned int jdy = bytesperline / 4 - width; + unsigned int dx = (img->bufwidth << 10) / width; TDEBUG_START - for(y = 0; y < ximg->height; y++){ - unsigned int bufx = img->bufwidth / ximg->width; - ibuf = &img->buf[y * img->bufheight / ximg->height * img->bufwidth * 3]; + for(y = 0; y < height; y++){ + unsigned int bufx = img->bufwidth / width; + ibuf = &img->buf[y * img->bufheight / height * img->bufwidth * 3]; - for(x = 0; x < ximg->width; x++){ + for(x = 0; x < width; x++){ *newBuf++ = (ibuf[(bufx >> 10)*3+2]); *newBuf++ = (ibuf[(bufx >> 10)*3+1]); *newBuf++ = (ibuf[(bufx >> 10)*3+0]); diff --git a/src/xlib.c b/src/xlib.c index ca0a1b5..a407f15 100644 --- a/src/xlib.c +++ b/src/xlib.c @@ -21,9 +21,6 @@ GC gc; int xshm = 0; -void scale(struct image *img, XImage *ximg); -void linearscale(struct image *img, XImage *ximg); - XShmSegmentInfo *shminfo; XImage *ximage(struct image *img, unsigned int width, unsigned int height, int fast){ int depth; @@ -71,7 +68,7 @@ XImage *ximage(struct image *img, unsigned int width, unsigned int height, int f ximg->data = malloc(ximg->bytes_per_line * ximg->height); XInitImage(ximg); } - (fast ? linearscale : scale)(img, ximg); + (fast ? nearestscale : scale)(img, ximg->width, ximg->height, ximg->bytes_per_line, ximg->data); }else{ /* TODO other depths */ fprintf(stderr, "This program does not yet support display depths <24.\n"); diff --git a/test/test.c b/test/test.c new file mode 100644 index 0000000..926d5c2 --- /dev/null +++ b/test/test.c @@ -0,0 +1,62 @@ +#include "stdio.h" +#include "stdlib.h" +#include "sys/time.h" + +#include "../src/meh.h" + +#define TESTRUNS 20 +#define STARTTEST(name) int test_##name(){ testname = #name; testsrun++; do +#define ENDTEST while(0); testspassed++; return 0;} +#define STARTTIME struct timeval tvs[2];int _i, _j; for(_i = 0; _i < 2; gettimeofday(&tvs[_i], NULL), _i++){for(_j = 0; _j < (_i ? TESTRUNS : 3); _j++) +#define ENDTIME }long int mselapsed = (tvs[1].tv_sec - tvs[0].tv_sec) * 1000000L + (tvs[1].tv_usec - tvs[0].tv_usec); printf("%s: average time: %li.%.3li ms\n", testname, mselapsed/1000/TESTRUNS, (mselapsed/TESTRUNS)%1000); +#define assert(x) if(!(x)){fprintf(stderr, "test \"%s\" failed\n assert(%s) was false\n at %s:%i\n\n", testname, #x, __FILE__ ,__LINE__);return -1;} + +char *testname = NULL; +int testsrun = 0, testspassed = 0; + +typedef int (*test_t)(); + +STARTTEST(scale){ + struct image img; + img.bufwidth = 1280*2; + img.bufheight = 1024*2; + img.buf = malloc(img.bufwidth*img.bufheight*4); + char *to = malloc(1280*1024*4); + STARTTIME{ + scale(&img, 1280, 1024, 1280, to); + }ENDTIME + free(to); + free(img.buf); +}ENDTEST + +STARTTEST(nearestscale){ + struct image img; + img.bufwidth = 1280*2; + img.bufheight = 1024*2; + img.buf = malloc(img.bufwidth*img.bufheight*4); + char *to = malloc(1280*1024*4); + STARTTIME{ + nearestscale(&img, 1280, 1024, 1280, to); + }ENDTIME + free(to); + free(img.buf); +}ENDTEST + +test_t tests[] = { + test_scale, + test_nearestscale, + NULL +}; + +void summary(){ + printf("%i tests run: %i passed %i failed\n", testsrun, testspassed, testsrun - testspassed); +} + +int main(){ + test_t *test = tests; + for(; *test; test++) + (*test)(); + summary(); + return 0; +} + diff --git a/test/test.h b/test/test.h new file mode 100644 index 0000000..1f2e7a0 --- /dev/null +++ b/test/test.h @@ -0,0 +1,6 @@ + +#define STARTTIME +#define ENDTIME + +#define + -- cgit v1.2.3