Churchyard (talk | contribs) (More shout-outs) |
Churchyard (talk | contribs) |
||
Line 84: | Line 84: | ||
<pre> | <pre> | ||
+-------------------------+------------------+------------------------------+ | +-------------------------+------------------------------+------------------------------+ | ||
| Benchmark | python38-3.8.0-1 | python38-3.8.0- | | Benchmark | python38-3.8.0-1 (original) | python38-3.8.0-2 (changed) | | ||
+=========================+==================+==============================+ | +=========================+==============================+==============================+ | ||
| | | scimark_lu | 294 ms | 213 ms: 1.38x faster (-27%) | | ||
+-------------------------+------------------ | +-------------------------+------------------------------+------------------------------+ | ||
| scimark_sparse_mat_mult | 8.61 ms | 6.39 ms: 1.35x faster (-26%) | | |||
+-------------------------+------------------+------------------------------+ | +-------------------------+------------------------------+------------------------------+ | ||
| | | nbody | 236 ms | 179 ms: 1.32x faster (-24%) | | ||
+-------------------------+------------------ | +-------------------------+------------------------------+------------------------------+ | ||
| | | django_template | 203 ms | 158 ms: 1.29x faster (-22%) | | ||
+-------------------------+------------------+------------------------------+ | +-------------------------+------------------------------+------------------------------+ | ||
| | | raytrace | 910 ms | 709 ms: 1.28x faster (-22%) | | ||
+-------------------------+------------------ | +-------------------------+------------------------------+------------------------------+ | ||
| | | logging_format | 17.7 us | 13.8 us: 1.28x faster (-22%) | | ||
+-------------------------+------------------+------------------------------+ | +-------------------------+------------------------------+------------------------------+ | ||
| | | richards | 124 ms | 97.2 ms: 1.27x faster (-21%) | | ||
+-------------------------+------------------+------------------------------+ | +-------------------------+------------------------------+------------------------------+ | ||
| | | unpickle | 23.9 us | 18.8 us: 1.27x faster (-21%) | | ||
+-------------------------+------------------+------------------------------+ | +-------------------------+------------------------------+------------------------------+ | ||
| | | chaos | 200 ms | 158 ms: 1.26x faster (-21%) | | ||
+-------------------------+------------------+------------------------------+ | +-------------------------+------------------------------+------------------------------+ | ||
| hexiom | 17. | | hexiom | 17.6 ms | 14.0 ms: 1.26x faster (-21%) | | ||
+-------------------------+------------------ | +-------------------------+------------------------------+------------------------------+ | ||
| | | logging_simple | 15.8 us | 12.5 us: 1.26x faster (-21%) | | ||
+-------------------------+------------------+------------------------------+ | +-------------------------+------------------------------+------------------------------+ | ||
| nqueens | | | nqueens | 179 ms | 142 ms: 1.26x faster (-20%) | | ||
+-------------------------+------------------ | +-------------------------+------------------------------+------------------------------+ | ||
| logging_silent | 340 ns | 273 ns: 1.25x faster (-20%) | | |||
+-------------------------+------------------+------------------------------+ | +-------------------------+------------------------------+------------------------------+ | ||
| | | crypto_pyaes | 201 ms | 162 ms: 1.24x faster (-19%) | | ||
+-------------------------+------------------+------------------------------+ | +-------------------------+------------------------------+------------------------------+ | ||
| | | scimark_fft | 653 ms | 527 ms: 1.24x faster (-19%) | | ||
+-------------------------+------------------+------------------------------+ | +-------------------------+------------------------------+------------------------------+ | ||
| | | scimark_monte_carlo | 190 ms | 154 ms: 1.24x faster (-19%) | | ||
+-------------------------+------------------+------------------------------+ | +-------------------------+------------------------------+------------------------------+ | ||
| | | pickle_pure_python | 795 us | 646 us: 1.23x faster (-19%) | | ||
+-------------------------+------------------+------------------------------+ | +-------------------------+------------------------------+------------------------------+ | ||
| | | go | 443 ms | 361 ms: 1.23x faster (-18%) | | ||
+-------------------------+------------------+------------------------------+ | +-------------------------+------------------------------+------------------------------+ | ||
| | | deltablue | 12.6 ms | 10.4 ms: 1.22x faster (-18%) | | ||
+-------------------------+------------------+------------------------------+ | +-------------------------+------------------------------+------------------------------+ | ||
| | | spectral_norm | 245 ms | 201 ms: 1.22x faster (-18%) | | ||
+-------------------------+------------------+------------------------------+ | +-------------------------+------------------------------+------------------------------+ | ||
| | | float | 203 ms | 167 ms: 1.21x faster (-18%) | | ||
+-------------------------+------------------ | +-------------------------+------------------------------+------------------------------+ | ||
| | | mako | 27.0 ms | 22.2 ms: 1.21x faster (-18%) | | ||
+-------------------------+------------------+------------------------------+ | +-------------------------+------------------------------+------------------------------+ | ||
| | | scimark_sor | 347 ms | 286 ms: 1.21x faster (-17%) | | ||
+-------------------------+------------------+------------------------------+ | +-------------------------+------------------------------+------------------------------+ | ||
| | | unpickle_pure_python | 575 us | 475 us: 1.21x faster (-17%) | | ||
+-------------------------+------------------+------------------------------+ | +-------------------------+------------------------------+------------------------------+ | ||
| | | fannkuch | 803 ms | 667 ms: 1.20x faster (-17%) | | ||
+-------------------------+------------------+------------------------------+ | +-------------------------+------------------------------+------------------------------+ | ||
| | | pathlib | 35.3 ms | 29.5 ms: 1.20x faster (-17%) | | ||
+-------------------------+------------------+------------------------------+ | +-------------------------+------------------------------+------------------------------+ | ||
| | | pyflate | 1.15 sec | 959 ms: 1.19x faster (-16%) | | ||
+-------------------------+------------------+------------------------------+ | +-------------------------+------------------------------+------------------------------+ | ||
| | | sympy_expand | 707 ms | 600 ms: 1.18x faster (-15%) | | ||
+-------------------------+------------------+------------------------------+ | +-------------------------+------------------------------+------------------------------+ | ||
| | | regex_compile | 303 ms | 258 ms: 1.18x faster (-15%) | | ||
+-------------------------+------------------+------------------------------+ | +-------------------------+------------------------------+------------------------------+ | ||
| | | chameleon | 15.7 ms | 13.3 ms: 1.18x faster (-15%) | | ||
+-------------------------+------------------+------------------------------+ | +-------------------------+------------------------------+------------------------------+ | ||
| | | sympy_str | 461 ms | 394 ms: 1.17x faster (-15%) | | ||
+-------------------------+------------------+------------------------------+ | +-------------------------+------------------------------+------------------------------+ | ||
| | | genshi_xml | 104 ms | 88.4 ms: 1.17x faster (-15%) | | ||
+-------------------------+------------------+------------------------------+ | +-------------------------+------------------------------+------------------------------+ | ||
| | | dulwich_log | 116 ms | 100 ms: 1.16x faster (-14%) | | ||
+-------------------------+------------------+------------------------------+ | +-------------------------+------------------------------+------------------------------+ | ||
| | | sympy_integrate | 34.4 ms | 29.9 ms: 1.15x faster (-13%) | | ||
+-------------------------+------------------+------------------------------+ | +-------------------------+------------------------------+------------------------------+ | ||
| | | genshi_text | 49.1 ms | 42.9 ms: 1.15x faster (-13%) | | ||
+-------------------------+------------------+------------------------------+ | +-------------------------+------------------------------+------------------------------+ | ||
| | | 2to3 | 535 ms | 471 ms: 1.14x faster (-12%) | | ||
+-------------------------+------------------+------------------------------+ | +-------------------------+------------------------------+------------------------------+ | ||
| | | json_dumps | 20.4 ms | 18.0 ms: 1.13x faster (-12%) | | ||
+-------------------------+------------------+------------------------------+ | +-------------------------+------------------------------+------------------------------+ | ||
| | | sympy_sum | 285 ms | 252 ms: 1.13x faster (-12%) | | ||
+-------------------------+------------------ | +-------------------------+------------------------------+------------------------------+ | ||
| xml_etree_process | 128 ms | 114 ms: 1.12x faster (-11%) | | |||
+-------------------------+----------------- | +-------------------------+------------------------------+------------------------------+ | ||
| sqlite_synth | 4.75 us | 4.24 us: 1.12x faster (-11%) | | |||
+-------------------------+------------------------------+------------------------------+ | |||
| telco | 10.1 ms | 8.98 ms: 1.12x faster (-11%) | | |||
+-------------------------+------------------+------------------------------+ | +-------------------------+------------------------------+------------------------------+ | ||
| | | meteor_contest | 168 ms | 150 ms: 1.12x faster (-11%) | | ||
+-------------------------+------------------+------------------------------+ | +-------------------------+------------------------------+------------------------------+ | ||
| | | sqlalchemy_imperative | 53.3 ms | 47.7 ms: 1.12x faster (-11%) | | ||
+-------------------------+------------------+------------------------------+ | +-------------------------+------------------------------+------------------------------+ | ||
| | | tornado_http | 425 ms | 382 ms: 1.11x faster (-10%) | | ||
+-------------------------+------------------+------------------------------+ | +-------------------------+------------------------------+------------------------------+ | ||
| | | xml_etree_generate | 159 ms | 144 ms: 1.10x faster (-9%) | | ||
+-------------------------+------------------+------------------------------+ | +-------------------------+------------------------------+------------------------------+ | ||
| | | sqlalchemy_declarative | 271 ms | 251 ms: 1.08x faster (-7%) | | ||
+-------------------------+------------------+------------------------------+ | +-------------------------+------------------------------+------------------------------+ | ||
| | | json_loads | 43.5 us | 40.4 us: 1.08x faster (-7%) | | ||
+-------------------------+------------------ | +-------------------------+------------------------------+------------------------------+ | ||
| python_startup | 13.9 ms | 13.1 ms: 1.06x faster (-6%) | | |||
+-------------------------+------------------+------------------------------+ | +-------------------------+------------------------------+------------------------------+ | ||
| | | unpickle_list | 6.68 us | 6.29 us: 1.06x faster (-6%) | | ||
+-------------------------+------------ | +-------------------------+------------------------------+------------------------------+ | ||
</pre> | </pre> | ||
Revision as of 13:08, 15 November 2019
Build Python with -fno-semantic-interposition for better performance
Summary
We add the -fno-semantic-interposition
compiler/linker flag when building Python interpreters, as it provides significant performance improvement, up to 27% depending on the workload. Users will no longer be able to use LD_PRELOAD to override a symbol from libpython, which we consider a good trade off for the speedup.
Owner
- Name: Charalampos Stratakis, Victor Stinner, Miro Hrončok
- Email: python-maint@redhat.com
- Shout-out: Jan Kratochvíl for first suggesting this instead of the original proposal, followed by Kevin Kofler. Florian Weimer for providing answers to our questions. David Gray for originally suggesting to link Python statically to gain performance.
Current status
- Targeted release: Fedora 32
- Last updated: 2019-11-15
- Tracker bug: <will be assigned by the Wrangler>
- Release notes tracker: <will be assigned by the Wrangler>
Detailed Description
When we build the Python interpreter with the -fno-semantic-interposition
compiler/linker flag, we can achieve a performance gain of 5% to 27% depending on the workload. Link time optimizations and profile guided optimizations also have a greater impact when python3 is built this way.
As a negative side effect, it disables the LD_PRELOAD feature: it's no longer possible to override symbols in libpython with LD_PRELOAD. Thanks to that, the compiler can avoid PLT indirection for function calls and can inline more function functions in libpython. We're describing function calls from libpython to libpython, something which is very common in Python: almost all function calls are calls from libpython to libpython.
If Fedora users need to use LD_PRELOAD to override symbols in libpython, the recommend way is to build a custom Python without -fno-semantic-interposition
.
Affected Pythons
Primarily, we will change the interpreter in the python3
package, that is Python 3.8 in Fedora 32 and any later version of Python in future Fedora releases.
Impact on other Python packages (and generally software using Python) is not anticipated (other than the possible speedup).
We will also change the alternate Python interpreters where possible and useful, primarily the upstream supported versions of CPython, such as python39
(if already packaged), python37
, python36
and python35
.
Benefit to Fedora
Python's performance will increase significantly depending on the workload. Since many core components of the OS also depend on Python this could lead to an increase in their performance as well, however individual benchmarks will need to be conducted to verify the performance gain for those components.
pyperformance results, ignoring differences smaller than 5%:
+-------------------------+------------------------------+------------------------------+ | Benchmark | python38-3.8.0-1 (original) | python38-3.8.0-2 (changed) | +=========================+==============================+==============================+ | scimark_lu | 294 ms | 213 ms: 1.38x faster (-27%) | +-------------------------+------------------------------+------------------------------+ | scimark_sparse_mat_mult | 8.61 ms | 6.39 ms: 1.35x faster (-26%) | +-------------------------+------------------------------+------------------------------+ | nbody | 236 ms | 179 ms: 1.32x faster (-24%) | +-------------------------+------------------------------+------------------------------+ | django_template | 203 ms | 158 ms: 1.29x faster (-22%) | +-------------------------+------------------------------+------------------------------+ | raytrace | 910 ms | 709 ms: 1.28x faster (-22%) | +-------------------------+------------------------------+------------------------------+ | logging_format | 17.7 us | 13.8 us: 1.28x faster (-22%) | +-------------------------+------------------------------+------------------------------+ | richards | 124 ms | 97.2 ms: 1.27x faster (-21%) | +-------------------------+------------------------------+------------------------------+ | unpickle | 23.9 us | 18.8 us: 1.27x faster (-21%) | +-------------------------+------------------------------+------------------------------+ | chaos | 200 ms | 158 ms: 1.26x faster (-21%) | +-------------------------+------------------------------+------------------------------+ | hexiom | 17.6 ms | 14.0 ms: 1.26x faster (-21%) | +-------------------------+------------------------------+------------------------------+ | logging_simple | 15.8 us | 12.5 us: 1.26x faster (-21%) | +-------------------------+------------------------------+------------------------------+ | nqueens | 179 ms | 142 ms: 1.26x faster (-20%) | +-------------------------+------------------------------+------------------------------+ | logging_silent | 340 ns | 273 ns: 1.25x faster (-20%) | +-------------------------+------------------------------+------------------------------+ | crypto_pyaes | 201 ms | 162 ms: 1.24x faster (-19%) | +-------------------------+------------------------------+------------------------------+ | scimark_fft | 653 ms | 527 ms: 1.24x faster (-19%) | +-------------------------+------------------------------+------------------------------+ | scimark_monte_carlo | 190 ms | 154 ms: 1.24x faster (-19%) | +-------------------------+------------------------------+------------------------------+ | pickle_pure_python | 795 us | 646 us: 1.23x faster (-19%) | +-------------------------+------------------------------+------------------------------+ | go | 443 ms | 361 ms: 1.23x faster (-18%) | +-------------------------+------------------------------+------------------------------+ | deltablue | 12.6 ms | 10.4 ms: 1.22x faster (-18%) | +-------------------------+------------------------------+------------------------------+ | spectral_norm | 245 ms | 201 ms: 1.22x faster (-18%) | +-------------------------+------------------------------+------------------------------+ | float | 203 ms | 167 ms: 1.21x faster (-18%) | +-------------------------+------------------------------+------------------------------+ | mako | 27.0 ms | 22.2 ms: 1.21x faster (-18%) | +-------------------------+------------------------------+------------------------------+ | scimark_sor | 347 ms | 286 ms: 1.21x faster (-17%) | +-------------------------+------------------------------+------------------------------+ | unpickle_pure_python | 575 us | 475 us: 1.21x faster (-17%) | +-------------------------+------------------------------+------------------------------+ | fannkuch | 803 ms | 667 ms: 1.20x faster (-17%) | +-------------------------+------------------------------+------------------------------+ | pathlib | 35.3 ms | 29.5 ms: 1.20x faster (-17%) | +-------------------------+------------------------------+------------------------------+ | pyflate | 1.15 sec | 959 ms: 1.19x faster (-16%) | +-------------------------+------------------------------+------------------------------+ | sympy_expand | 707 ms | 600 ms: 1.18x faster (-15%) | +-------------------------+------------------------------+------------------------------+ | regex_compile | 303 ms | 258 ms: 1.18x faster (-15%) | +-------------------------+------------------------------+------------------------------+ | chameleon | 15.7 ms | 13.3 ms: 1.18x faster (-15%) | +-------------------------+------------------------------+------------------------------+ | sympy_str | 461 ms | 394 ms: 1.17x faster (-15%) | +-------------------------+------------------------------+------------------------------+ | genshi_xml | 104 ms | 88.4 ms: 1.17x faster (-15%) | +-------------------------+------------------------------+------------------------------+ | dulwich_log | 116 ms | 100 ms: 1.16x faster (-14%) | +-------------------------+------------------------------+------------------------------+ | sympy_integrate | 34.4 ms | 29.9 ms: 1.15x faster (-13%) | +-------------------------+------------------------------+------------------------------+ | genshi_text | 49.1 ms | 42.9 ms: 1.15x faster (-13%) | +-------------------------+------------------------------+------------------------------+ | 2to3 | 535 ms | 471 ms: 1.14x faster (-12%) | +-------------------------+------------------------------+------------------------------+ | json_dumps | 20.4 ms | 18.0 ms: 1.13x faster (-12%) | +-------------------------+------------------------------+------------------------------+ | sympy_sum | 285 ms | 252 ms: 1.13x faster (-12%) | +-------------------------+------------------------------+------------------------------+ | xml_etree_process | 128 ms | 114 ms: 1.12x faster (-11%) | +-------------------------+------------------------------+------------------------------+ | sqlite_synth | 4.75 us | 4.24 us: 1.12x faster (-11%) | +-------------------------+------------------------------+------------------------------+ | telco | 10.1 ms | 8.98 ms: 1.12x faster (-11%) | +-------------------------+------------------------------+------------------------------+ | meteor_contest | 168 ms | 150 ms: 1.12x faster (-11%) | +-------------------------+------------------------------+------------------------------+ | sqlalchemy_imperative | 53.3 ms | 47.7 ms: 1.12x faster (-11%) | +-------------------------+------------------------------+------------------------------+ | tornado_http | 425 ms | 382 ms: 1.11x faster (-10%) | +-------------------------+------------------------------+------------------------------+ | xml_etree_generate | 159 ms | 144 ms: 1.10x faster (-9%) | +-------------------------+------------------------------+------------------------------+ | sqlalchemy_declarative | 271 ms | 251 ms: 1.08x faster (-7%) | +-------------------------+------------------------------+------------------------------+ | json_loads | 43.5 us | 40.4 us: 1.08x faster (-7%) | +-------------------------+------------------------------+------------------------------+ | python_startup | 13.9 ms | 13.1 ms: 1.06x faster (-6%) | +-------------------------+------------------------------+------------------------------+ | unpickle_list | 6.68 us | 6.29 us: 1.06x faster (-6%) | +-------------------------+------------------------------+------------------------------+
Scope
- Proposal owners:
- Review and merge the pull request with the implementation.
- Go through the Python C extension packages that are linked to libpython and test if things work correctly. A copr repository will be provided for testing.
- Other developers: Other developers are encouraged to test the new statically linked python3 and check if their package works as expected
- Release engineering: #8953 This change does not require a mass rebuild, however a rebuild of the affected packages will be required. The affected packages will be rebuilt in copr first.
- Policies and guidelines: The packaging guidelines will need to be updated to explicitly mention that C extensions should not be linked to libpython, and that the python3 binary is statically linked.
- Trademark approval: N/A (not needed for this Change)
Upgrade/compatibility impact
Affected package maintainers should verify that their packages work as expected and the only impact the end users should see is a performance increase for workloads relying on Python.
How To Test
Copr repo with instructions: https://copr.fedorainfracloud.org/coprs/g/python/Python3_statically_linked/
Package changes test
The change will bring the new libpython3
subpackage as a dependency of python3-devel
.
Test that it's installed:
$ rpm -q libpython3
Test that it's uninstalled if python3-devel
is removed:
$ dnf remove python3-devel
Test that python3-libs
no longer includes the libpython shared library.
$ rpm -ql python3-libs | grep libpython3
Dynamic linker test
To check that the python3.8 program is not linked to libpython, ldd can be used. For example, Python 3.7 will still be linked to libpython:
$ ldd /usr/bin/python3.7|grep libpython libpython3.7m.so.1.0 => /lib64/libpython3.7m.so.1.0 (0x00007fbb57333000)
But python3.8 will no longer be linked to libpython:
$ ldd /usr/bin/python3.8|grep libpython
Performance test
The performance speedup can be measured using the official Python benchmark suite pyperformance: see Run benchmarks.
Namespace test
The following script can be used to verify that the change is in effect:
import ctypes import sys EMPTY_TUPLE_SINGLETON = () def get_empty_tuple(lib): # Call PyTuple_New(0) func = lib.PyTuple_New func.argtypes = (ctypes.c_ssize_t,) func.restype = ctypes.py_object return func(0) def test_lib(libname, lib): obj = get_empty_tuple(lib) if obj is EMPTY_TUPLE_SINGLETON: print("%s: SAME namespace" % libname) else: print("%s: DIFFERENT namespace" % libname) def test(): program = ctypes.pythonapi if hasattr(sys, 'abiflags'): abiflags = sys.abiflags else: # Python 2 abiflags = '' ver = sys.version_info filename = ('libpython%s.%s%s.so.1.0' % (ver.major, ver.minor, abiflags)) libpython = ctypes.cdll.LoadLibrary(filename) test_lib('program', program) test_lib('libpython', libpython) test()
Output before the change:
program: SAME namespace libpython: SAME namespace
Output after the change:
program: SAME namespace libpython: DIFFERENT namespace
User Experience
Python based workloads should see a performance gain of up to 27%.
Dependencies
While this specific change is not dependent on anything else, we would like to ensure that all the packages that link to libpython continue to work as expected.
Currently (30/10/2019) 118 packages on rawhide depend on libpython.
Result of the "repoquery --repo=rawhide --source --whatrequires 'libpython3.8.so.1.0()(64bit)' " command on Fedora Rawhide, x86_64:
- COPASI
- Io-language
- OpenImageIO
- YafaRay
- antimony
- blender
- boost
- calamares
- calibre
- cantor
- ceph
- clingo
- condor
- createrepo_c
- csound
- cvc4
- dionaea
- dmlite
- domoticz
- fontforge
- freecad
- gdb
- gdcm
- gdl
- getdp
- glade
- globus-net-manager
- glom
- gnucash
- gpaw
- hamlib
- hokuyoaist
- hugin
- insight
- kdevelop-python
- kicad
- kitty
- krita
- lammps
- ldns
- libCombine
- libarcus https://src.fedoraproject.org/rpms/libarcus/pull-request/8
- libarcus-lulzbot
- libbatch
- libcec
- libcomps
- libdnf
- libftdi
- libkml
- libkolabxml
- libldb
- libnuml
- libpeas
- libplist
- libreoffice
- librepo
- libsavitar
- libsbml
- libsedml
- libtalloc
- libyang
- libyui-bindings
- link-grammar
- lldb
- mathgl
- med
- mod_wsgi
- nautilus-python
- nbdkit
- nest
- netgen-mesher
- neuron
- nextpnr
- nordugrid-arc
- nwchem
- openbabel
- openscap
- opentrep
- openvdb
- pam_wrapper
- paraview
- perl-Inline-Python
- pidgin
- pitivi
- plplot
- postgresql
- pynac
- pyotherside
- pythia8
- python-gstreamer1
- python-jep
- python-qt5
python3- qgis
- qpid-dispatch
- qpid-proton
- rdkit
- renderdoc
- rmol
- root
- samba
- scidavis
- sigil
- swift-lang
- texworks
- thunarx-python
- trademgen
- trellis
- unbound
- uwsgi
- vdr-epg-daemon
- vigra
- vim
- vrpn
- vtk
- weechat
- znc
Packages in bold are the ones present in the default docker/podman "fedora:rawhide" image.
Contingency Plan
- Contingency mechanism: If issues appear that cannot be fixed in a timely manner the change can be easily reverted and will be considered again for the next fedora release. Also a proper upgrade path mechanism will be provided in case of reversion, since libpython.3.?.so will be a separate package with this change.
- Contingency deadline: Before the beta freeze of Fedora 32 (2020-02-25)
- Blocks release? Yes
- Blocks product? None
Documentation
The documentation will be reflected in the changes for the python packaging guidelines.