- Overall
- Motivation
- Performance Improvement
- Setup
- Development
- Technical Details
6.1 Common Binary Encoding Differences between C Extension and Original Ion Python
6.2 Known Issues - TODO
- Deploy
8.1 Distribution
Ion Python C extension utilizes Ion C to access files that close the performance gap between the Ion Python simpleion module and other Ion implementations.
The simpleion module C extension supports limited options for now and will add more incrementally. Refer to TODO for details.
Python is not fast which causes Ion Python to be slower than other Ion implementations. Ion Python is also slower than other similar python data serialization libraries such as simplejson which is a JSON encoder and decoder. The main reason for the difference in performance between Simplejson and Ion Python simpleion module is because Simplejson binds to a C extension while Ion Python is implemented purely in python.
There are couple technologies we can choose for binding C extension and C binaries (Ion C): CFFI, Cython and CPython APIs.
CFFI and Ctypes are slower than CPython and Cython for most of our use case, Cython is a little bit faster than CPython but it's a compiler for a new programming language that requires more development time. One of the most challenging issues no matter which tool we use is that how we distribute Ion C binaries as it's .dylib
on Mac, .so
on Linux and .lib
on Windows. Also, CPython C extension code for simpleion was almost completed 2 years ago so we decided to choose this option.
If the performance becomes our biggest concern in the future, we should reevaluate the performance implications of the C extension to make sure we're keeping up with the innovations in the Python C extension ecosystem.
The performance improvement depends on a multitude of variables (e.g., how the files are structured, what APIs are called the most). Experiment results show around 6000% improvement for text writer/reader and 1400% improvement for binary writer/reader.
We use timeit
module to measure the execution time.
setup = "from amazon.ion import simpleion"
code = '''
with open("file_name", "br") as fp:
simpleion.dumps(simpleion.load(fp, single_value=False))
'''
print(timeit.timeit(setup=setup, stmt=code, number=1))
test-driver-report.ion(10n)
are reports generated by ion-test-driver which consists of Ion structs and strings.
log.ion(10n)
are logs that contain a variety of scalar types, annotations, and nested containers.
Files | C extension | Ion Python | Improvement |
---|---|---|---|
test-driver-report.ion (42MB) | 3.8s | 217s | 5611% |
test-driver-report.10n (13.7MB) | 3.6s | 55s | 1428% |
log.ion (84MB) | 14.8s | 987s | 6569% |
log.10n (14MB) | 15s | 221s | 1373% |
Ensure that cmake is installed. The setup for Ion Python C extension is the same as the original Ion Python Setup. If it runs into any issue during initialization, it will fall back to regular Ion Python. No extra action needed.
C extension is built under ion-python/amazon/ion
and named according to the following format (may be slightly different depending on your platform) ionc.cpython-$py_version-$platform.$suffix
(e.g., ionc.cpython-39-darwin.so)
>>> import amazon.ion.simpleion as ion
>>> obj = ion.loads('{abc: 123}')
>>> obj['abc']
123
>>> ion.dumps(obj, binary=True)
b'\xe0\x01\x00\xea\xe9\x81\x83\xd6\x87\xb4\x83abc\xd3\x8a!{'
Architecture of Ion Python C extension:
ioncmodule.c
|
|
↓
Ion C -------> Ion C binaries -----> setup.py ------> C extension -------------------> Ion Python simpleion module
compile setup import ionc module
After setup, C extension will be built and imported to simpleion module. If there are changes in ioncmodule.c
, build the latest C extension by running python setup.py build_ext --inplace
.
Note that both binary encodings are equivalent; one encoding is not more "correct" than the other.
1.1 Different ways to represent a struct's length. Refer to Amazon Ion Binary Encoding for details.
For Ion struct {a:2}
:
Text IVM ion_symbol_table::{ symbols:[”a”]} { “a”: 2 }
Ion C \xe0\x01\x00\xea \xe7\x81\x83 \xd4 \x87\xb2\x81a \xd3 \x8a 21\x02
Ion Python \xe0\x01\x00\xea \xe8\x81\x83 \xde\x84 \x87\xb2\x81a \xde\x83 \x8a 21\x02
For symbol abc
with two annotations annot1
and annot2
, annot1::annot2::abc
:
Ion C text ion_symbol_table::{ symbols:[ "abc", "annot1", "annot2"]} annot1($11)::annot2($12)::abc($10)
Ion C binary \xee\x99\x81\x83 \xde\x95 \x87\xbe\x92 \x83abc\x86annot1\x86annot2 \xe5\x82 \x8b \x8c \x71\x0a
Ion Python binary ion_symbol_table::{ symbols:[ "annot1", "annot2", "abc",]} annot1($10)::annot2($11)::abc($12)
ion Python \xee\x99\x81\x83 \xde\x95 \x87\xbe\x92 \x86annot1\x86annot2\x83abc \xe5\x82 \x8a \x8b \x71\x0c
- C extension only supports at most 9 for timestamp precision. Refer to amazon-ion/ion-python#160 for details.
- C extension only supports at most 34 decimal digits. Refer to amazon-ion/ion-python#159 for details.
- C extension has a limitation to read large Clob data. Refer to amazon-ion/ion-python#207 for details.
- For any memory leak issue, please comment on amazon-ion/ion-python#155.
- More bug fixing.
- More performance improvement.
- Support more simpleion options such as
imports
,catalog
,omit_version_marker
. (Ion Python uses pure python implementation to handle unsupported options currently) - Support pretty print.
PYPI supports two ways of distribution: Source Code Distribution and Wheel Distribution. We support both of them.
Note that the benefits of wheel distribution are:
- Pre-compiling Ion C library avoids potential build/compile issues and does not require a C compiler to be present on the user's machine.
- Installation of wheels is faster and more efficient.