Created
May 9, 2016 02:35
-
-
Save kernigh/d169895a700c6511d08511c005a28d88 to your computer and use it in GitHub Desktop.
benchmark for different random number generators
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Run benchmarks: | |
# $ ruby benchrand.rb | |
# Run benchmarks in parallel with sh and xterm: | |
# $ for i in 1 2; do xterm -hold -e ruby benchrand.rb& done | |
# | |
# Outputs the time to generate SIZE random bytes with several | |
# different random number generators: | |
# - Random::DEFAULT from Ruby | |
# - /dev/urandom | |
# - arc4random_buf() from libc | |
# - RAND_bytes() from OpenSSL | |
# - gnutls_rnd() from GnuTLS | |
# - PK11_GenerateRandom() from NSS | |
# | |
# This script skips generators that it can't find. You may need to | |
# edit the Fiddle.dlopen() calls in this script. | |
require 'benchmark' | |
require 'fiddle' | |
SIZE = 256 * 1024**2 | |
# copied from <gnutls/crypto.h> | |
GNUTLS_RND_NONCE = 0 | |
GNUTLS_RND_RANDOM = 1 | |
GNUTLS_RND_KEY = 2 | |
# copied from <nss/seccommon.h> | |
SECSuccess = 0 | |
urandom = (open('/dev/urandom', 'rb') rescue warn "Don't have urandom") | |
libc = (Fiddle.dlopen('libc.so') rescue nil) | |
libcrypto = (Fiddle.dlopen('libcrypto.so') rescue nil) | |
libgnutls = (Fiddle.dlopen('libgnutls.so') rescue nil) | |
libnss3 = (Fiddle.dlopen('libssl3.so') rescue nil) | |
def function(lib, name, par, ret) | |
if sym = (lib[name] rescue nil) | |
Fiddle::Function.new(sym, par, ret) | |
else | |
warn "Don't have #{name}" | |
end | |
end | |
int = Fiddle::TYPE_INT | |
size_t = Fiddle::TYPE_SIZE_T | |
void = Fiddle::TYPE_VOID | |
voidp = Fiddle::TYPE_VOIDP | |
arc4random_buf = function(libc, 'arc4random_buf', [voidp, size_t], void) | |
rand_bytes = function(libcrypto, 'RAND_bytes', [voidp, int], int) | |
gnutls_rnd = function(libgnutls, 'gnutls_rnd', [int, voidp, size_t], int) | |
pk11_GenerateRandom = function(libnss3, 'PK11_GenerateRandom', | |
[voidp, int], int) | |
if pk11_GenerateRandom | |
nss_NoDB_Init = function(libnss3, 'NSS_NoDB_Init', [voidp], int) | |
end | |
def with_buf | |
begin | |
yield buf = Fiddle::Pointer.malloc(SIZE) | |
ensure | |
Fiddle.free buf | |
end | |
end | |
Benchmark.bm(20) do |x| | |
x.report('Random::DEFAULT') { | |
Random::DEFAULT.bytes(SIZE) | |
} | |
urandom && x.report('/dev/urandom') { | |
str = urandom.read(SIZE) | |
str.length == SIZE or warn 'urandom met EOF' | |
} | |
arc4random_buf && x.report('arc4random_buf') { | |
with_buf {|buf| arc4random_buf.(buf, SIZE)} | |
} | |
rand_bytes && x.report('RAND_bytes') { | |
with_buf {|buf| rand_bytes.(buf, SIZE)} | |
} | |
if gnutls_rnd | |
x.report('gnutls_rnd NONCE') { | |
with_buf {|buf| gnutls_rnd.(GNUTLS_RND_NONCE, buf, SIZE)} | |
} | |
x.report('gnutls_rnd RANDOM') { | |
with_buf {|buf| gnutls_rnd.(GNUTLS_RND_RANDOM, buf, SIZE)} | |
} | |
x.report('gnutls_rnd KEY') { | |
with_buf {|buf| gnutls_rnd.(GNUTLS_RND_KEY, buf, SIZE)} | |
} | |
end | |
pk11_GenerateRandom && x.report('PK11_GenerateRandom') { | |
# It fails if we did not initialize it. | |
nss_NoDB_Init.(0) == SECSuccess or fail 'NSS_NoDB_Init failed' | |
with_buf {|buf| | |
offset = 0 | |
while offset < SIZE | |
# It fails if we request more than 65536 bytes. | |
req = [65536, SIZE - offset].min | |
pk11_GenerateRandom.(buf + offset, req) == SECSuccess or | |
fail 'PK11_GenerateRandom failed' | |
offset += req | |
end | |
} | |
} | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment