cpython icon indicating copy to clipboard operation
cpython copied to clipboard

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

Open NewUserHa opened this issue 2 years ago • 8 comments

  • Issue: gh-99305

NewUserHa avatar Nov 09 '22 23:11 NewUserHa

All commit authors signed the Contributor License Agreement.
CLA signed

cpython-cla-bot[bot] avatar Nov 09 '22 23:11 cpython-cla-bot[bot]

Most changes to Python require a NEWS entry.

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

bedevere-bot avatar Nov 09 '22 23:11 bedevere-bot

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

eendebakpt avatar Nov 10 '22 08:11 eendebakpt

Done.

NewUserHa avatar Nov 10 '22 12:11 NewUserHa

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)

eendebakpt avatar Nov 10 '22 12:11 eendebakpt

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

https://github.com/python/cpython/blob/cb04a09d2dfd197436a11de504b92773569e19fb/Objects/bytesobject.c#L2482 https://github.com/python/cpython/blob/f07adf82f338ebb7e69475537be050e63c2009fa/Modules/clinic/binascii.c.h#L486 binascii.hexlify() works the same with bytes.hex() + encode() but has different implements. merging may get another free performance boost that can faster python.

NewUserHa avatar Nov 10 '22 13:11 NewUserHa

import binascii can be removed from the module probably

illia-v avatar Nov 10 '22 13:11 illia-v

right, import binascii removed.

NewUserHa avatar Nov 10 '22 13:11 NewUserHa