benchmark.py revision 12391:ceeca8b41e4b
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_MODULE(example, m) {\n"
37    result += bindings
38    result += "}"
39    return result
40
41
42def generate_dummy_code_boost(nclasses=10):
43    decl = ""
44    bindings = ""
45
46    for cl in range(nclasses):
47        decl += "class cl%03i;\n" % cl
48    decl += '\n'
49
50    for cl in range(nclasses):
51        decl += "class cl%03i {\n" % cl
52        decl += "public:\n"
53        bindings += '    py::class_<cl%03i>("cl%03i")\n' % (cl, cl)
54        for fn in range(nfns):
55            ret = random.randint(0, nclasses - 1)
56            params  = [random.randint(0, nclasses - 1) for i in range(nargs)]
57            decl += "    cl%03i *fn_%03i(" % (ret, fn)
58            decl += ", ".join("cl%03i *" % p for p in params)
59            decl += ");\n"
60            bindings += '        .def("fn_%03i", &cl%03i::fn_%03i, py::return_value_policy<py::manage_new_object>())\n' % \
61                (fn, cl, fn)
62        decl += "};\n\n"
63        bindings += '        ;\n'
64
65    result = "#include <boost/python.hpp>\n\n"
66    result += "namespace py = boost::python;\n\n"
67    result += decl + '\n'
68    result += "BOOST_PYTHON_MODULE(example) {\n"
69    result += bindings
70    result += "}"
71    return result
72
73
74for codegen in [generate_dummy_code_pybind11, generate_dummy_code_boost]:
75    print ("{")
76    for i in range(0, 10):
77        nclasses = 2 ** i
78        with open("test.cpp", "w") as f:
79            f.write(codegen(nclasses))
80        n1 = dt.datetime.now()
81        os.system("g++ -Os -shared -rdynamic -undefined dynamic_lookup "
82            "-fvisibility=hidden -std=c++14 test.cpp -I include "
83            "-I /System/Library/Frameworks/Python.framework/Headers -o test.so")
84        n2 = dt.datetime.now()
85        elapsed = (n2 - n1).total_seconds()
86        size = os.stat('test.so').st_size
87        print("   {%i, %f, %i}," % (nclasses * nfns, elapsed, size))
88    print ("}")
89