summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bench/.gitignore5
-rw-r--r--bench/Makefile132
-rw-r--r--bench/bench.c121
-rwxr-xr-xbench/runbench.sh22
4 files changed, 280 insertions, 0 deletions
diff --git a/bench/.gitignore b/bench/.gitignore
new file mode 100644
index 0000000..4d8fd6b
--- /dev/null
+++ b/bench/.gitignore
@@ -0,0 +1,5 @@
+*
+!.gitignore
+!Makefile
+!bench.c
+!runbench.sh
diff --git a/bench/Makefile b/bench/Makefile
new file mode 100644
index 0000000..de5cf42
--- /dev/null
+++ b/bench/Makefile
@@ -0,0 +1,132 @@
+# The tests are compiled and linked using musl-cross. The advantage of this is
+# that everything is self-contained and thus easy to reproduce. Musl is also
+# designed for static linking with little overhead, which gives us a good
+# metric for the "complete package" of a statically linked minimal XML reader
+# for each lib.
+
+FILE1=enwiki-20130805-abstract5.xml
+FILE1URL=http://dumps.wikimedia.org/enwiki/20130805/enwiki-20130805-abstract5.xml
+FILE2=discogs_20130801_labels.xml
+FILE2URL=http://www.discogs.com/data/${FILE2}.gz
+FILES=${FILE1} ${FILE2}
+MUSLCROSS=x86_64-linux-musl
+MUSLCROSSURL=https://bitbucket.org/GregorR/musl-cross/downloads/crossx86-x86_64-linux-musl-0.9.11.tar.xz
+EXPAT=expat-2.1.0
+EXPATURL=http://downloads.sourceforge.net/project/expat/expat/2.1.0/${EXPAT}.tar.gz
+LIBXML2=libxml2-2.9.1
+LIBXML2URL=ftp://xmlsoft.org/libxml2/${LIBXML2}.tar.gz
+MXML=mxml-2.7
+MXMLURL=http://www.msweet.org/files/project3/${MXML}.tar.gz
+
+HOST=x86_64-musl-linux
+CC=${HOST}-gcc
+AR=${HOST}-ar
+STRIP=${HOST}-strip
+export CFLAGS = -static -O2
+export PATH := ${PATH}:${PWD}/${MUSLCROSS}/bin
+
+.PHONY: notice all clean distclean
+
+notice:
+ @echo "You probably don't want to 'make' these benchmarks."
+ @echo "Lots of stuff is downloaded, lots of stuff is compiled and lots of stuff is run."
+ @echo "Run 'make all -j1' if you do have the patience to run the benchmarks."
+ @echo
+ @false
+
+build: strlen yxml expat libxml2 mxml
+all: strlen-bench yxml-bench expat-bench libxml2-bench mxml-bench
+
+${FILE1}:
+ curl ${FILE1URL} -O ${FILE1}
+
+${FILE2}:
+ @echo "This doesn't work. Probably want to download the file manually with a browser"
+ curl ${FILE2URL} | zcat > ${FILE2}
+
+${MUSLCROSS}:
+ curl -L ${MUSLCROSSURL} | xzcat | tar -xvf-
+
+${EXPAT}:
+ curl -L ${EXPATURL} | zcat | tar -xvf-
+
+${LIBXML2}:
+ curl ${LIBXML2URL} | zcat | tar -xvf-
+
+${MXML}:
+ curl ${MXMLURL} | zcat | tar -xvf-
+
+
+
+yxml.o: ../yxml.c
+ make -C .. yxml.c
+ ${CC} ${CFLAGS} -I.. ../yxml.c -c
+
+yxml: ${MUSLCROSS} bench.c yxml.o
+ ${CC} ${CFLAGS} -I.. -DYXML bench.c yxml.o -o yxml
+ ${STRIP} -s yxml
+
+yxml-bench: yxml ${FILES}
+ ./runbench.sh yxml.o yxml ${FILES}
+
+
+
+strlen: ${MUSLCROSS} bench.c
+ ${CC} ${CFLAGS} -DSTRLEN bench.c -o strlen
+ ${STRIP} -s strlen
+
+strlen-bench: strlen ${FILES}
+ ./runbench.sh strlen strlen ${FILES}
+
+
+
+libexpat.a: ${MUSLCROSS} ${EXPAT}
+ cd ${EXPAT} && ./configure --disable-shared --host=${HOST} && make buildlib
+ cp ${EXPAT}/.libs/libexpat.a libexpat.a
+
+expat: libexpat.a bench.c
+ ${CC} ${CFLAGS} -I${EXPAT}/lib -DEXPAT bench.c -L. -lexpat -o expat
+ ${STRIP} -s expat
+
+expat-bench: expat ${FILES}
+ ./runbench.sh libexpat.a expat ${FILES}
+
+
+
+libxml2.a: ${MUSLCROSS} ${LIBXML2}
+ @# So many options, yet --with-minimum and --without-output don't seem to work
+ cd ${LIBXML2} && ./configure --disable-shared --without-c14n --without-catalog --without-debug\
+ --without-docbook --without-ftp --without-html --without-http --without-iconv --without-iso8859x\
+ --without-legacy --without-pattern --without-push --without-regexps --without-sax1\
+ --without-schemas --without-schematron --without-threads --without-tree --without-valid\
+ --without-writer --without-xinclude --without-xpath --without-xpath --without-modules\
+ --without-zlib --without-lzma --host ${HOST} && make libxml2.la
+ cp ${LIBXML2}/.libs/libxml2.a libxml2.a
+
+libxml2: libxml2.a bench.c
+ ${CC} ${CFLAGS} -I${LIBXML2}/include -DLIBXML2 bench.c -L. -lxml2 -o libxml2
+ ${STRIP} -s libxml2
+
+libxml2-bench: libxml2 ${FILES}
+ ./runbench.sh libxml2.a libxml2 ${FILES}
+
+
+
+libmxml.a: ${MUSLCROSS} ${MXML}
+ cd ${MXML} && ./configure --disable-shared --disable-threads --host ${HOST} && make libmxml.a
+ cp ${MXML}/libmxml.a libmxml.a
+
+mxml: libmxml.a bench.c
+ ${CC} ${CFLAGS} -I${MXML} -DMXML bench.c -L. -lmxml -o mxml
+ ${STRIP} -s mxml
+
+mxml-bench: mxml ${FILES}
+ ./runbench.sh libmxml.a mxml ${FILES}
+
+
+
+clean:
+ rm -f *.a *.o *-bench yxml strlen expat libxml2 mxml
+
+distclean:
+ rm -rf ${MUSLCROSS} ${FILES} ${EXPAT} ${LIBXML2} ${MXML}
diff --git a/bench/bench.c b/bench/bench.c
new file mode 100644
index 0000000..f354dba
--- /dev/null
+++ b/bench/bench.c
@@ -0,0 +1,121 @@
+/* Copyright (c) 2013 Yoran Heling
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <assert.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#if defined(STRLEN)
+static void xmlbench(const char *buf, size_t bufsize) {
+ size_t l = strlen(buf);
+ assert(l == bufsize);
+}
+
+
+#elif defined(YXML)
+#include <yxml.h>
+static void xmlbench(const char *buf, size_t bufsize) {
+ yxml_t x[1];
+ char *stack = malloc(4096);
+ yxml_init(x, stack, 4096);
+ yxml_ret_t r;
+ do {
+ r = yxml_parse(x, *buf);
+ buf++;
+ } while(*buf && r >= 0 && r != YXML_EOD);
+ /*printf("t%03lu l%03u b%03lu: %c %d", x->total, x->line, x->byte, *buf, r);*/
+ assert(!*buf);
+}
+
+
+#elif defined(EXPAT)
+#include <expat.h>
+static void xmlbench(const char *buf, size_t bufsize) {
+ XML_Parser p = XML_ParserCreate(NULL);
+ int r = XML_Parse(p, buf, bufsize, 1);
+ assert(r != XML_STATUS_ERROR);
+ XML_ParserFree(p);
+}
+
+
+#elif defined(LIBXML2)
+#include <libxml/xmlreader.h>
+static void xmlbench(const char *buf, size_t bufsize) {
+ xmlTextReaderPtr p = xmlReaderForMemory(buf, bufsize, NULL, NULL, 0);
+ while(xmlTextReaderRead(p) == 1)
+ ;
+ xmlFreeTextReader(p);
+}
+
+
+#elif defined(MXML)
+#include <mxml.h>
+static void sax_cb(mxml_node_t *node, mxml_sax_event_t event, void *data) {
+ static int i;
+ /* Only retain the root node, to make sure that we don't get NULL. */
+ if(event == MXML_SAX_ELEMENT_OPEN && !i) {
+ mxmlRetain(node);
+ i=1;
+ }
+}
+static void xmlbench(const char *buf, size_t bufsize) {
+ mxml_node_t *n = mxmlSAXLoadString(NULL, buf, MXML_NO_CALLBACK, sax_cb, NULL);
+ assert(n);
+}
+
+
+#else
+#error No idea what to bench
+#endif
+
+
+int main(int argc, char **argv) {
+ struct stat st;
+ ssize_t r;
+
+ assert(argc == 2);
+ r = stat(argv[1], &st);
+ assert(!r);
+
+ char *buf = malloc(st.st_size+1);
+ assert(buf);
+
+ int fd = open(argv[1], O_RDONLY);
+ assert(fd > 0);
+
+ ssize_t rd = read(fd, buf, st.st_size);
+ assert(rd == st.st_size);
+ buf[st.st_size] = 0;
+ close(fd);
+
+ xmlbench(buf, st.st_size);
+ return 0;
+}
+
+/* vim: set noet sw=4 ts=4: */
diff --git a/bench/runbench.sh b/bench/runbench.sh
new file mode 100755
index 0000000..77b4e50
--- /dev/null
+++ b/bench/runbench.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+OBJ=$1
+shift
+PROG=$1
+shift
+
+if test -z $OBJ; then
+ echo "This script is supposed to be run from 'make'."
+ exit 1
+fi
+
+echo "====> Benchmark results for $PROG" >$PROG-bench
+size -t $OBJ | tail -n 1 >>$PROG-bench
+wc -c $PROG >>$PROG-bench
+
+for i in $@; do
+ echo "== $i" >>$PROG-bench
+ cat $i >/dev/null
+ sh -c "time ./$PROG $i" >>$PROG-bench 2>&1
+ sh -c "time ./$PROG $i" >>$PROG-bench 2>&1
+done