Update benchmark suite with fair timing and micropython support

This commit is contained in:
K. Lange 2021-04-16 19:58:05 +09:00
parent de76ba5394
commit e4db90d392
12 changed files with 111 additions and 7 deletions

View File

@ -10,5 +10,3 @@ jobs:
run: make clean && make
- name: Test
run: make test
- name: Benchmark
run: make bench

View File

@ -155,6 +155,8 @@ bench:
@for i in bench/*.krk; do ./kuroko "$$i"; done
@echo "CPython:"
@for i in bench/*.py; do python3 "$$i"; done
@echo "Micropython:"
@for i in bench/*.py; do micropython -X heapsize=128M "$$i"; done
# Really should be up to you to set, not us...
multiarch ?= $(shell gcc -print-multiarch)

View File

@ -120,10 +120,10 @@ def write_instancevar():
a.x = 1; a.x = 1; a.x = 1; a.x = 1; a.x = 1
if __name__=='__main__':
from timeit import timeit
from fasttimer import timeit
for f in [read_local, read_nonlocal, read_global, read_builtin,
read_classvar, read_instancevar, read_unboundmethod, read_boundmethod,
write_local, write_nonlocal, write_global,
write_classvar, write_instancevar]:
print(timeit(f,number=1000000), f.__qualname__)
print(timeit(f,number=1000000), f.__qualname__ if hasattr(f,'__qualname__') else f.__name__ if hasattr(f,'__name__') else '?')

2
bench/fasttimer/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
build/
__pycache__/

8
bench/fasttimer/Makefile Normal file
View File

@ -0,0 +1,8 @@
all: _fasttimer.so _mpytimer.so
_fasttimer.so: py_fasttimer.c
python3 setup.py build
cp build/*/*.so ./$@
_mpytimer.so: mpy_timer.c
$(CC) -shared -o $@ $<

View File

@ -0,0 +1,13 @@
try:
from ._fasttimer import timeit
except:
import ffi
path = __file__.split('/')[:-1]
if not path: path = '.'
else: path = '/'.join(path)
lib = ffi.open(path + '/_mpytimer.so')
_timeit = lib.func('d','timeit','Ci')
def timeit(callback,number=1000000):
cb = ffi.callback('v',callback,'')
return _timeit(cb,number)

View File

@ -0,0 +1,18 @@
#include <time.h>
#include <sys/time.h>
double
timeit(void (*callback)(void), int times)
{
struct timeval tv_before, tv_after;
gettimeofday(&tv_before,NULL);
for (int t = 0; t < times; ++t) {
callback();
}
gettimeofday(&tv_after,NULL);
double before = (double)tv_before.tv_sec + (double)tv_before.tv_usec / 1000000.0;
double after = (double)tv_after.tv_sec + (double)tv_after.tv_usec / 1000000.0;
return after-before;
}

View File

@ -0,0 +1,59 @@
#define PY_SSIZE_T_CLEAN
#include <Python.h>
#include <time.h>
#include <sys/time.h>
static PyObject *
fasttimer_timeit(PyObject * self, PyObject * args, PyObject* kwargs)
{
PyObject * callable;
int times = 1000000;
static char * keywords[] = {"callable","number",NULL};
if (!PyArg_ParseTupleAndKeywords(args,kwargs,"O|i:timeit",
keywords, &callable, &times)) {
PyErr_SetString(PyExc_TypeError, "bad arguments?");
return NULL;
}
if (!PyCallable_Check(callable)) {
PyErr_SetString(PyExc_TypeError, "expected callable");
return NULL;
}
Py_XINCREF(callable);
struct timeval tv_before, tv_after;
gettimeofday(&tv_before,NULL);
for (int t = 0; t < times; ++t) {
/* Call it here */
PyObject_CallObject(callable, NULL);
}
gettimeofday(&tv_after,NULL);
Py_XDECREF(callable);
double before = (double)tv_before.tv_sec + (double)tv_before.tv_usec / 1000000.0;
double after = (double)tv_after.tv_sec + (double)tv_after.tv_usec / 1000000.0;
return PyFloat_FromDouble(after-before);
}
static PyMethodDef FasttimerMethods[] = {
{"timeit", (PyCFunction)(void(*)(void))fasttimer_timeit, METH_VARARGS | METH_KEYWORDS, "Call a callable in a tight loop."},
{NULL,NULL,0,NULL},
};
static struct PyModuleDef fasttimermodule = {
PyModuleDef_HEAD_INIT,
"fasttimer",
NULL,
-1,
FasttimerMethods
};
PyMODINIT_FUNC
PyInit__fasttimer(void)
{
return PyModule_Create(&fasttimermodule);
}

4
bench/fasttimer/setup.py Normal file
View File

@ -0,0 +1,4 @@
from distutils.core import setup, Extension
fasttimer = Extension('_fasttimer',sources=['py_fasttimer.c'])
setup(name="_fasttimer",version='1.0',description='fast timer',ext_modules=[fasttimer])

View File

@ -5,6 +5,6 @@ def __main__():
fib(30)
if __name__ == '__main__':
from timeit import timeit
from fasttimer import timeit
print(timeit(__main__,number=1),'fib(30)')

View File

@ -1,4 +1,4 @@
from timeit import timeit
from fasttimer import timeit
l = []
add = l.append

View File

@ -10,5 +10,5 @@ def makeTree(depth):
return Node(n1,n2)
if __name__ == '__main__':
from timeit import timeit
from fasttimer import timeit
print(timeit(lambda: makeTree(16), number=10), 'makeTree')