STINNER Victor <vstin...@python.org> added the comment:

I wrote a quick benchmark:
---
import pyperf
import random

gen = random.Random()
# gen = random.SystemRandom()
gen.seed(850779834)

if 1: #hasattr(gen, 'randbytes'):
    func = type(gen).randbytes
elif 0:
    def py_randbytes(gen, n):
        data = bytearray(n)
        i = 0
        while i < n:
            chunk = 4
            word = gen.getrandbits(32)
            word = word.to_bytes(4, 'big')
            chunk = min(n, 4)
            data[i:i+chunk] = word[:chunk]
            i += chunk
        return bytes(data)

    func = py_randbytes
else:
    def getrandbits_to_bytes(gen, n):
        return gen.getrandbits(n * 8).to_bytes(n, 'little')

    func = getrandbits_to_bytes

runner = pyperf.Runner()
for nbytes in (1, 4, 16, 1024, 1024 * 1024):
    runner.bench_func(f'randbytes({nbytes})', func, gen, nbytes)
---

Results on Linux using gcc -O3 (without LTO or PGO) using the C randbytes() 
implementation as the reference:

+--------------------+-------------+----------------------------------+-------------------------------+
| Benchmark          | c_randbytes | py_randbytes                     | 
getrandbits_to_bytes          |
+====================+=============+==================================+===============================+
| randbytes(1)       | 71.4 ns     | 1.04 us: 14.51x slower (+1351%)  | 244 ns: 
3.42x slower (+242%)  |
+--------------------+-------------+----------------------------------+-------------------------------+
| randbytes(4)       | 71.4 ns     | 1.03 us: 14.48x slower (+1348%)  | 261 ns: 
3.66x slower (+266%)  |
+--------------------+-------------+----------------------------------+-------------------------------+
| randbytes(16)      | 81.9 ns     | 3.07 us: 37.51x slower (+3651%)  | 321 ns: 
3.92x slower (+292%)  |
+--------------------+-------------+----------------------------------+-------------------------------+
| randbytes(1024)    | 1.05 us     | 173 us: 165.41x slower (+16441%) | 3.66 
us: 3.49x slower (+249%) |
+--------------------+-------------+----------------------------------+-------------------------------+
| randbytes(1048576) | 955 us      | 187 ms: 196.30x slower (+19530%) | 4.37 
ms: 4.58x slower (+358%) |
+--------------------+-------------+----------------------------------+-------------------------------+

* c_randbytes: PR 19527, randbytes() methods implemented in C
* py_randbytes: bytearray, getrandbits(), .to_bytes()
* getrandbits_to_bytes: Serhiy's implementation: gen.getrandbits(n * 
8).to_bytes(n, 'little')

So well, the C randbytes() implementation is always the fastest.


random.SystemRandom().randbytes() (os.urandom(n)) performance using 
random.Random().randbytes() (Mersenne Twister) as a reference:

+--------------------+-------------+---------------------------------+
| Benchmark          | c_randbytes | systemrandom                    |
+====================+=============+=================================+
| randbytes(1)       | 71.4 ns     | 994 ns: 13.93x slower (+1293%)  |
+--------------------+-------------+---------------------------------+
| randbytes(4)       | 71.4 ns     | 1.04 us: 14.60x slower (+1360%) |
+--------------------+-------------+---------------------------------+
| randbytes(16)      | 81.9 ns     | 1.02 us: 12.49x slower (+1149%) |
+--------------------+-------------+---------------------------------+
| randbytes(1024)    | 1.05 us     | 6.22 us: 5.93x slower (+493%)   |
+--------------------+-------------+---------------------------------+
| randbytes(1048576) | 955 us      | 5.64 ms: 5.91x slower (+491%)   |
+--------------------+-------------+---------------------------------+

os.urandom() is way slower than Mersenne Twister.

Well, that's not surprising: os.urandom() requires at least one syscall 
(getrandom() syscall on my Linux machine).

----------

_______________________________________
Python tracker <rep...@bugs.python.org>
<https://bugs.python.org/issue40286>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to