FAQ improvements

This commit is contained in:
Wenzel Jakob 2016-04-17 21:54:31 +02:00
parent 8cb6cb33ef
commit c79dbe425d
2 changed files with 99 additions and 1 deletions

View File

@ -5,7 +5,7 @@ Changelog
1.5 (not yet released) 1.5 (not yet released)
---------------------- ----------------------
* For polymorphic types, use RTTI to try to return the closest type registered with pybind11. * For polymorphic types, use RTTI to try to return the closest type registered with pybind11
* Pickling support for serializing and unserializing C++ instances to a byte stream in Python * Pickling support for serializing and unserializing C++ instances to a byte stream in Python
* Added a convenience routine ``make_iterator()`` which turns a range indicated * Added a convenience routine ``make_iterator()`` which turns a range indicated
by a pair of C++ iterators into a iterable Python object by a pair of C++ iterators into a iterable Python object

View File

@ -97,3 +97,101 @@ that that were ``malloc()``-ed in another shared library, using data
structures with incompatible ABIs, and so on. pybind11 is very careful not structures with incompatible ABIs, and so on. pybind11 is very careful not
to make these types of mistakes. to make these types of mistakes.
How can I reduce the build time?
================================
It's good practice to split binding code over multiple files, as is done in
the included file :file:`example/example.cpp`.
.. code-block:: cpp
void init_ex1(py::module &);
void init_ex2(py::module &);
/* ... */
PYBIND11_PLUGIN(example) {
py::module m("example", "pybind example plugin");
init_ex1(m);
init_ex2(m);
/* ... */
return m.ptr();
}
The various ``init_ex`` functions are contained in separate files that can be
compiled independently from another. Following this approach will
1. enable parallel builds (if desired).
2. allow for faster incremental builds (e.g. if a single class definiton is
changed, only a subset of the binding code may need to be recompiled).
3. reduce memory requirements.
How can I create smaller binaries?
==================================
To do its job, pybind11 extensively relies on a programming technique known as
*template metaprogramming*, which is a way of performing computation at compile
time using type information. Template metaprogamming usually instantiates code
involving significant numbers of deeply nested types that are either completely
removed or reduced to just a few instrutions during the compiler's optimization
phase. However, due to the nested nature of these types, the resulting symbol
names in the compiled extension library can be extremely long. For instance,
the included test suite contains the following symbol:
.. code-block:: cpp
__ZN8pybind1112cpp_functionC1Iv8Example2JRNSt3__16vectorINS3_12basic_stringIwNS3_11char_traitsIwEENS3_9allocatorIwEEEENS8_ISA_EEEEEJNS_4nameENS_7siblingENS_9is_methodEA28_cEEEMT0_FT_DpT1_EDpRKT2_
which is the mangled form of the following function type:
.. code-block:: cpp
pybind11::cpp_function::cpp_function<void, Example2, std::__1::vector<std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> >, std::__1::allocator<std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> > > >&, pybind11::name, pybind11::sibling, pybind11::is_method, char [28]>(void (Example2::*)(std::__1::vector<std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> >, std::__1::allocator<std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> > > >&), pybind11::name const&, pybind11::sibling const&, pybind11::is_method const&, char const (&) [28])
The memory needed to store just the name of this function (196 bytes) is larger
than the actual piece of code (111 bytes) it represents! On the other hand,
it's silly to even give this function a name -- after all, it's just a tiny
cog in a bigger piece of machinery that is not exposed to the outside world.
So we'll generally only want to export symbols for those functions which are
actually called from the outside.
This can be achieved by specifying the parameter ``-fvisibility=hidden`` to GCC
and Clang, which sets the default symbol visibility to *hidden*. It's best to
do this only for release builds, since the symbol names can be helpful in
debugging sessions. On Visual Studio, symbols are already hidden by default, so
nothing needs to be done there. Needless to say, this has a tremendous impact
on the final binary size of the resulting extension library.
Another aspect that can require a fair bit of code are function signature
descriptions. pybind11 automatically generates human-readable function
signatures for docstrings, e.g.:
.. code-block:: none
| __init__(...)
| __init__(*args, **kwargs)
| Overloaded function.
|
| 1. __init__(example.Example1) -> NoneType
|
| Docstring for overload #1 goes here
|
| 2. __init__(example.Example1, int) -> NoneType
|
| Docstring for overload #2 goes here
|
| 3. __init__(example.Example1, example.Example1) -> NoneType
|
| Docstring for overload #3 goes here
In C++11 mode, these are generated at run time using string concatenation,
which can amount to 10-20% of the size of the resulting binary. If you can,
enable C++14 language features (using ``-std=c++14`` for GCC/Clang), in which
case signatures are efficiently pre-generated at compile time. Unfortunately,
Visual Studio's C++14 support (``constexpr``) is not good enough as of April
2016, so it always uses the more expensive run-time approach.