Blame external/pybind11/docs/benchmark.rst

Packit 534379
Benchmark
Packit 534379
=========
Packit 534379
Packit 534379
The following is the result of a synthetic benchmark comparing both compilation
Packit 534379
time and module size of pybind11 against Boost.Python. A detailed report about a
Packit 534379
Boost.Python to pybind11 conversion of a real project is available here: [#f1]_.
Packit 534379
Packit 534379
.. [#f1] http://graylab.jhu.edu/RosettaCon2016/PyRosetta-4.pdf
Packit 534379
Packit 534379
Setup
Packit 534379
-----
Packit 534379
Packit 534379
A python script (see the ``docs/benchmark.py`` file) was used to generate a set
Packit 534379
of files with dummy classes whose count increases for each successive benchmark
Packit 534379
(between 1 and 2048 classes in powers of two). Each class has four methods with
Packit 534379
a randomly generated signature with a return value and four arguments. (There
Packit 534379
was no particular reason for this setup other than the desire to generate many
Packit 534379
unique function signatures whose count could be controlled in a simple way.)
Packit 534379
Packit 534379
Here is an example of the binding code for one class:
Packit 534379
Packit 534379
.. code-block:: cpp
Packit 534379
Packit 534379
    ...
Packit 534379
    class cl034 {
Packit 534379
    public:
Packit 534379
        cl279 *fn_000(cl084 *, cl057 *, cl065 *, cl042 *);
Packit 534379
        cl025 *fn_001(cl098 *, cl262 *, cl414 *, cl121 *);
Packit 534379
        cl085 *fn_002(cl445 *, cl297 *, cl145 *, cl421 *);
Packit 534379
        cl470 *fn_003(cl200 *, cl323 *, cl332 *, cl492 *);
Packit 534379
    };
Packit 534379
    ...
Packit 534379
Packit 534379
    PYBIND11_MODULE(example, m) {
Packit 534379
        ...
Packit 534379
        py::class_<cl034>(m, "cl034")
Packit 534379
            .def("fn_000", &cl034::fn_000)
Packit 534379
            .def("fn_001", &cl034::fn_001)
Packit 534379
            .def("fn_002", &cl034::fn_002)
Packit 534379
            .def("fn_003", &cl034::fn_003)
Packit 534379
        ...
Packit 534379
    }
Packit 534379
Packit 534379
The Boost.Python version looks almost identical except that a return value
Packit 534379
policy had to be specified as an argument to ``def()``. For both libraries,
Packit 534379
compilation was done with
Packit 534379
Packit 534379
.. code-block:: bash
Packit 534379
Packit 534379
    Apple LLVM version 7.0.2 (clang-700.1.81)
Packit 534379
Packit 534379
and the following compilation flags
Packit 534379
Packit 534379
.. code-block:: bash
Packit 534379
Packit 534379
    g++ -Os -shared -rdynamic -undefined dynamic_lookup -fvisibility=hidden -std=c++14
Packit 534379
Packit 534379
Compilation time
Packit 534379
----------------
Packit 534379
Packit 534379
The following log-log plot shows how the compilation time grows for an
Packit 534379
increasing number of class and function declarations. pybind11 includes many
Packit 534379
fewer headers, which initially leads to shorter compilation times, but the
Packit 534379
performance is ultimately fairly similar (pybind11 is 19.8 seconds faster for
Packit 534379
the largest largest file with 2048 classes and a total of 8192 methods -- a
Packit 534379
modest **1.2x** speedup relative to Boost.Python, which required 116.35
Packit 534379
seconds).
Packit 534379
Packit 534379
.. only:: not latex
Packit 534379
Packit 534379
    .. image:: pybind11_vs_boost_python1.svg
Packit 534379
Packit 534379
.. only:: latex
Packit 534379
Packit 534379
    .. image:: pybind11_vs_boost_python1.png
Packit 534379
Packit 534379
Module size
Packit 534379
-----------
Packit 534379
Packit 534379
Differences between the two libraries become much more pronounced when
Packit 534379
considering the file size of the generated Python plugin: for the largest file,
Packit 534379
the binary generated by Boost.Python required 16.8 MiB, which was **2.17
Packit 534379
times** / **9.1 megabytes** larger than the output generated by pybind11. For
Packit 534379
very small inputs, Boost.Python has an edge in the plot below -- however, note
Packit 534379
that it stores many definitions in an external library, whose size was not
Packit 534379
included here, hence the comparison is slightly shifted in Boost.Python's
Packit 534379
favor.
Packit 534379
Packit 534379
.. only:: not latex
Packit 534379
Packit 534379
    .. image:: pybind11_vs_boost_python2.svg
Packit 534379
Packit 534379
.. only:: latex
Packit 534379
Packit 534379
    .. image:: pybind11_vs_boost_python2.png
Packit 534379
Packit 534379