Watch the screencast
SecureRandom is a common solution for generating simple, random strings in Ruby. But is it always the optimal approach?
In this video I demonstrate how SecureRandom can actually be quite a slow and expensive way to generate random strings, and walk through the steps for creating your own PORO that suits your specific domain.
RandomRef class
class RandomRef
CHARS = *'A'..'Z', *'0'..'9'
attr_reader :string
alias to_s string
def initialize(length: 10)
@string = CHARS.shuffle.take(length).join
end
end
Benchmark
Here’s the benchmark setup and results on my machine:
require "benchmark"
require_relative "random_ref"
require "securerandom"
TIMES_RUN = 10_000
Benchmark.bmbm do |test|
test.report("SecureRandom hex:") { TIMES_RUN.times { SecureRandom.hex(5).upcase } }
test.report("SecureRandom alpha:") { TIMES_RUN.times { SecureRandom.alphanumeric(10).upcase } }
test.report("RandomRef:") { TIMES_RUN.times { RandomRef.new.to_s } }
end
Rehearsal -------------------------------------------------------
SecureRandom hex: 0.017828 0.101192 0.119020 ( 0.119230)
SecureRandom alpha: 0.063555 0.243703 0.307258 ( 0.307377)
RandomRef: 0.013328 0.001197 0.014525 ( 0.014526)
---------------------------------------------- total: 0.440803sec
user system total real
SecureRandom hex: 0.019170 0.108771 0.127941 ( 0.128621)
SecureRandom alpha: 0.064643 0.246745 0.311388 ( 0.311942)
RandomRef: 0.013712 0.000642 0.014354 ( 0.014404)
Update 16/11/2020
I realised that RandomRef
will not return a truly random string, since it won’t have any repeat characters. While this isn’t a major problem, I’ve updated the episode code with a slight refactor that corrects this. Benchmarks for the updated version below:
class RandomRef
CHARS = *'A'..'Z', *'0'..'9'
attr_reader :string
alias to_s string
def initialize(length: 10)
@string = length.times.map { CHARS.sample }.join
end
end
Rehearsal -------------------------------------------------------
SecureRandom hex: 0.022391 0.142847 0.165238 ( 0.167282)
SecureRandom alpha: 0.071716 0.281742 0.353458 ( 0.354494)
RandomRef: 0.022149 0.001585 0.023734 ( 0.024165)
---------------------------------------------- total: 0.542430sec
user system total real
SecureRandom hex: 0.018336 0.117855 0.136191 ( 0.136656)
SecureRandom alpha: 0.071869 0.282151 0.354020 ( 0.356737)
RandomRef: 0.023950 0.000139 0.024089 ( 0.024159)
Explore the code
Explore the code from this screencast here: https://github.com/Bodacious/HandyRailsTips-EpisodeCode
Written by
Work with me
Need help with some code?
In my free time, I like to help people improve their code and skills
on Codementor.
Contact me on Codementor