diff --git a/ChangeLog b/ChangeLog index 14881a0a4d..7feb15a7fc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +Fri Aug 8 01:53:37 2014 Masaki Matsushita + + * lib/securerandom.rb: use OpenSSL::BN for performance improvement. + + * benchmark/bm_securerandom.rb: benchmark script. + Fri Aug 8 17:19:57 2014 SHIBATA Hiroshi * lib/open-uri.rb: remove needless condition for old ruby version. diff --git a/benchmark/bm_securerandom.rb b/benchmark/bm_securerandom.rb new file mode 100644 index 0000000000..a082ea6d5b --- /dev/null +++ b/benchmark/bm_securerandom.rb @@ -0,0 +1,5 @@ +require "securerandom" + +20_0000.times do + SecureRandom.random_number(100) +end diff --git a/lib/securerandom.rb b/lib/securerandom.rb index 3ff5075023..29368ee431 100644 --- a/lib/securerandom.rb +++ b/lib/securerandom.rb @@ -214,21 +214,29 @@ module SecureRandom # def self.random_number(n=0) if 0 < n - hex = n.to_s(16) - hex = '0' + hex if (hex.length & 1) == 1 - bin = [hex].pack("H*") - mask = bin[0].ord - mask |= mask >> 1 - mask |= mask >> 2 - mask |= mask >> 4 - begin - rnd = SecureRandom.random_bytes(bin.length) - rnd[0] = (rnd[0].ord & mask).chr - end until rnd < bin - rnd.unpack("H*")[0].hex + if defined? OpenSSL::BN + OpenSSL::BN.rand_range(n).to_i + else + hex = n.to_s(16) + hex = '0' + hex if (hex.length & 1) == 1 + bin = [hex].pack("H*") + mask = bin[0].ord + mask |= mask >> 1 + mask |= mask >> 2 + mask |= mask >> 4 + begin + rnd = SecureRandom.random_bytes(bin.length) + rnd[0] = (rnd[0].ord & mask).chr + end until rnd < bin + rnd.unpack("H*")[0].hex + end else # assumption: Float::MANT_DIG <= 64 - i64 = SecureRandom.random_bytes(8).unpack("Q")[0] + if defined? OpenSSL::BN + i64 = OpenSSL::BN.rand(64, -1).to_i + else + i64 = SecureRandom.random_bytes(8).unpack("Q")[0] + end Math.ldexp(i64 >> (64-Float::MANT_DIG), -Float::MANT_DIG) end end