Skip to content

gh-99305: secrets.token_hex() speeded up 2x #99306

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Nov 11, 2022
Merged

Conversation

NewUserHa
Copy link
Contributor

@NewUserHa NewUserHa commented Nov 9, 2022

@ghost
Copy link

ghost commented Nov 9, 2022

All commit authors signed the Contributor License Agreement.
CLA signed

@bedevere-bot
Copy link

Most changes to Python require a NEWS entry.

Please add it using the blurb_it web app or the blurb command-line tool.

@AlexWaygood AlexWaygood added type-feature A feature request or enhancement performance Performance or resource usage labels Nov 10, 2022
@eendebakpt
Copy link
Contributor

@NewUserHa Can you sign the CLA and write a news entry? The improvement looks good

@NewUserHa
Copy link
Contributor Author

Done.

@eendebakpt
Copy link
Contributor

The speed improvement depends on a bit on the number of bytes requested. A benchmark also taking the token_bytes into account:

nbytes=2048
%timeit binascii.hexlify(token_bytes(nbytes)).decode('ascii') 
%timeit token_bytes(nbytes).hex() 
# 3.5 µs ± 93.9 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
# 3 µs ± 106 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

nbytes=32
%timeit binascii.hexlify(token_bytes(nbytes)).decode('ascii') 
%timeit token_bytes(nbytes).hex() 
# 574 ns ± 62.9 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
# 426 ns ± 41.1 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

nbytes=1
%timeit binascii.hexlify(token_bytes(nbytes)).decode('ascii') 
%timeit token_bytes(nbytes).hex() 
# 414 ns ± 16.7 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
# 281 ns ± 2.71 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

@NewUserHa
Copy link
Contributor Author

right, taking token_bytes into account is only 1.2~1.4 time faster.
on my device

nbytes=2048
%timeit binascii.hexlify(token_bytes(nbytes)).decode('ascii') 
%timeit token_bytes(nbytes).hex() 
# 4.86 µs ± 449 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)
# 3.93 µs ± 87.3 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)
# 1.2366412213740458015267175572519 faster

nbytes=32
%timeit binascii.hexlify(token_bytes(nbytes)).decode('ascii') 
%timeit token_bytes(nbytes).hex() 
# 743 ns ± 66.8 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)
# 528 ns ± 28 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)
# 1.407196969696969696969696969697 faster

nbytes=1
%timeit binascii.hexlify(token_bytes(nbytes)).decode('ascii') 
%timeit token_bytes(nbytes).hex() 
# 652 ns ± 80.7 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)
# 442 ns ± 53.6 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)
# 1.2366412213740458015267175572519 faster
t = os.urandom(2048)
%timeit binascii.hexlify(t).decode('ascii')
%timeit t.hex()
# 3.69 µs ± 579 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)
# 2.78 µs ± 349 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)
# 1.3273381294964028776978417266187 faster

t = os.urandom(32)
%timeit binascii.hexlify(t).decode('ascii')
%timeit t.hex()
# 323 ns ± 112 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)
# 116 ns ± 3.33 ns per loop (mean ± std. dev. of 7 runs, 10,000,000 loops each)
# 2.7844827586206896551724137931034 faster

t = os.urandom(1)
%timeit binascii.hexlify(t).decode('ascii')
%timeit t.hex()
# 221 ns ± 13.7 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)
# 77.4 ns ± 1.97 ns per loop (mean ± std. dev. of 7 runs, 10,000,000 loops each)
# 2.8552971576227390180878552971576 faster

return _Py_strhex_with_sep(argbuf, arglen, sep, bytes_per_sep);

binascii_hexlify_impl(PyObject *module, Py_buffer *data, PyObject *sep,

binascii.hexlify() works the same with bytes.hex() + encode() but has different implements. merging may get another free performance boost that can faster python.

@illia-v
Copy link
Contributor

illia-v commented Nov 10, 2022

import binascii can be removed from the module probably

@NewUserHa
Copy link
Contributor Author

right, import binascii removed.

@gpshead gpshead merged commit 55c96e8 into python:main Nov 11, 2022
@python python deleted a comment Oct 13, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
performance Performance or resource usage type-feature A feature request or enhancement
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants