benchmark.py revision 11986:c12e4625ab56
1import random
2import os
3import time
4import datetime as dt
5
6nfns = 4  # Functions per class
7nargs = 4  # Arguments per function
8
9
10def generate_dummy_code_pybind11(nclasses=10):
11    decl = ""
12    bindings = ""
13
14    for cl in range(nclasses):
15        decl += "class cl%03i;\n" % cl
16    decl += '\n'
17
18    for cl in range(nclasses):
19        decl += "class cl%03i {\n" % cl
20        decl += "public:\n"
21        bindings += '    py::class_<cl%03i>(m, "cl%03i")\n' % (cl, cl)
22        for fn in range(nfns):
23            ret = random.randint(0, nclasses - 1)
24            params  = [random.randint(0, nclasses - 1) for i in range(nargs)]
25            decl += "    cl%03i *fn_%03i(" % (ret, fn)
26            decl += ", ".join("cl%03i *" % p for p in params)
27            decl += ");\n"
28            bindings += '        .def("fn_%03i", &cl%03i::fn_%03i)\n' % \
29                (fn, cl, fn)
30        decl += "};\n\n"
31        bindings += '        ;\n'
32
33    result = "#include <pybind11/pybind11.h>\n\n"
34    result += "namespace py = pybind11;\n\n"
35    result += decl + '\n'
36    result += "PYBIND11_PLUGIN(example) {\n"
37    result += "    py::module m(\"example\");"
38    result += bindings
39    result += "    return m.ptr();"
40    result += "}"
41    return result
42
43
44def generate_dummy_code_boost(nclasses=10):
45    decl = ""
46    bindings = ""
47
48    for cl in range(nclasses):
49        decl += "class cl%03i;\n" % cl
50    decl += '\n'
51
52    for cl in range(nclasses):
53        decl += "class cl%03i {\n" % cl
54        decl += "public:\n"
55        bindings += '    py::class_<cl%03i>("cl%03i")\n' % (cl, cl)
56        for fn in range(nfns):
57            ret = random.randint(0, nclasses - 1)
58            params  = [random.randint(0, nclasses - 1) for i in range(nargs)]
59            decl += "    cl%03i *fn_%03i(" % (ret, fn)
60            decl += ", ".join("cl%03i *" % p for p in params)
61            decl += ");\n"
62            bindings += '        .def("fn_%03i", &cl%03i::fn_%03i, py::return_value_policy<py::manage_new_object>())\n' % \
63                (fn, cl, fn)
64        decl += "};\n\n"
65        bindings += '        ;\n'
66
67    result = "#include <boost/python.hpp>\n\n"
68    result += "namespace py = boost::python;\n\n"
69    result += decl + '\n'
70    result += "BOOST_PYTHON_MODULE(example) {\n"
71    result += bindings
72    result += "}"
73    return result
74
75
76for codegen in [generate_dummy_code_pybind11, generate_dummy_code_boost]:
77    print ("{")
78    for i in range(0, 10):
79        nclasses = 2 ** i
80        with open("test.cpp", "w") as f:
81            f.write(codegen(nclasses))
82        n1 = dt.datetime.now()
83        os.system("g++ -Os -shared -rdynamic -undefined dynamic_lookup "
84            "-fvisibility=hidden -std=c++14 test.cpp -I include "
85            "-I /System/Library/Frameworks/Python.framework/Headers -o test.so")
86        n2 = dt.datetime.now()
87        elapsed = (n2 - n1).total_seconds()
88        size = os.stat('test.so').st_size
89        print("   {%i, %f, %i}," % (nclasses * nfns, elapsed, size))
90    print ("}")
91