size = 8; (1..size).map{([*('a'..'z')]+[*('A'..'Z')]+[*(1..9)].map{|n|n.to_s}).instance_eval{self[rand(self.size)]}}.join
size = 25; (0..size).inject('') { |r, i| r << rand(93) + 33 }
[*('a'..'z')]+[[*('A'..'Z')]+[*(1..9)]
is more than 10 times slower than defining it statically (you can hide it for code readability purposes)...
["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "1", "2", "3", "4", "5", "6", "7", "8", "9"]
On Ruby 1.9 (trunk code as of a week ago) dynamically defining the array is more than twice as slow as statically defining the constant array.
I ran a benchmark script that looks like http://pastie.caboo.se/154868 against:
Ruby 1.8.6p111 (no pthreads):
user system total real
dynamic 5.040000 1.710000 6.750000 ( 7.668346)
static 0.580000 0.040000 0.620000 ( 0.749564)
frozen 0.060000 0.020000 0.080000 ( 0.160672)
Ruby 1.9 (trunk as of last week):
user system total real
dynamic 1.200000 0.040000 1.240000 ( 1.694109)
static 0.540000 0.050000 0.590000 ( 0.717928)
frozen 0.010000 0.000000 0.010000 ( 0.018511)
So for systems that are generating a ton of random strings (many a second) using this code snippet, I would suggest the following rewrite:
# define frozen constant array somewhere meaningful for better reuse across the codebase # in some module or class define array... ALPHANUMS = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "1", "2", "3", "4", "5", "6", "7", "8", "9"].freeze # Also the instance_eval is now unnecessary when using an already defined array, which also saves on linear performance big time for high frequency calls to this. def generate_random_string(size) (1..size).map do (ALPHANUMS.map{|n|n.to_s})[rand(ALPHANUMS.size] end.join e
For those that run this code in your applications once or twice a day, I wouldn't bother worrying, but for others this might free up some system resources quicker.
For reference the #instance_eval call also has a fairly big impact. Run the following benchmark script on your machine to see the difference (2+ times faster on both 1.8.6p111[no pthreads] and 1.9-trunk on my old laptop): http://pastie.caboo.se/154895
You need to create an account or log in to post comments to this site.