Performance

Performance is compared between pyderasn==6.1, pyasn1==0.4.8 and asn1crypto==1.3.0. Decode CACert.org’s CRL (2019-02-08 state, 8.72 MiB), encode it, pickle decoded structure and unpickle it. Machine is Intel Core i5-6200U 2.3 GHz, 8 GB RAM, FreeBSD 12.0 amd64, Python 2.7.15 and Python 3.6.6 from native FreeBSD ports.

Code

pyasn1:

from pyasn1.codec.der.decoder import decode as der_decoder
from pyasn1.codec.der.encoder import encode as der_encoder
from pyasn1_modules.rfc5280 import CertificateList
with open("revoke.crl", "rb") as fd:
    raw = fd.read()
start = time()
crl, _ = der_decoder(raw, asn1Spec=CertificateList())
print("decode", time() - start)
del raw
gc.collect()
start = time()
der_encoder(c)
print("encode", time() - start)
# pyasn1 objects are not picklable

asn1crypto:

from asn1crypto.crl import CertificateList
with open("revoke.crl", "rb") as fd:
    raw = fd.read()
start = time()
crl = CertificateList.load(raw)
c.native  # full decoding and Python representation requires that
print("decode", time() - start)
del raw
gc.collect()
start = time()
crl.dump(force=True)  # forced DER encoding
print("encode", time() - start)
start = time()
raw = pickle.dumps(crl)
print("dumps", time() - start)
del crl
gc.collect()
print(len(raw))
start = time()
pickle.loads(raw)
print("loads", time() - start)

pyderasn:

from tests.test_crl import CertificateList
with open("revoke.crl", "rb") as fd:
    raw = fd.read()
start = time()
crl = CertificateList().decod(raw)
print("decode", time() - start)
del raw
gc.collect()
start = time()
crl.encode()
print("encode", time() - start)
start = time()
raw = pickle.dumps(crl)
print("dumps", time() - start)
del crl
gc.collect()
print(len(raw))
start = time()
pickle.loads(raw)
print("loads", time() - start)

Also there are cythonized asn1crypto and pyderasn versions, made using Cython==0.29.14, FreeBSD clang version 6.0.1 (tags/RELEASE_601/final 335540) (based on LLVM 6.0.1), CFLAGS=-O2 and Python 3 mode.

DER

Library Decode time, sec (Py36/Py27) Encode time, sec (Py36/Py27) Memory used, MiB (Py36/Py27)
pyasn1 1353 / 1400 37.5 / 36.7 1645 / 3296
asn1crypto 27.5 / 38 25.7 / 28 876 / 1742
cython asn1crypto 15.6 / N/A 15.8 / N/A 880 / N/A
pyderasn 33.2 / 33.4 7.6 / 7.4 560 / 516
cython pyderasn 23 / N/A 5.9 / N/A 561 / N/A

asn1crypto performs slightly better (with higher memory cost), but pay attention that it contains much less data for all objects (like offsets, sizes, etc) and it is not strict at all, passing possibly invalid DER structures! Also there are plenty of other Features it lacks.

pickle

pyasn1 objects are not pickable.

Library dumps time, sec (Py36/Py27) loads time, sec (Py36/Py27) Memory used, MiB (Py36/Py27) Size, MiB (Py36/Py27)
asn1crypto 7.9 / 145 8.3 / 91.4 2474 / 4944 174.8 / 373
pyderasn 82 / 244 17 / 77.8 3010 / 4372 110.5 / 248.6