Never been to DZone Snippets before?

Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world

ruby: random alphanumeric string (See related posts)

generate random alphanumeric string 'size' characters long

size = 8; (1..size).map{([*('a'..'z')]+[*('A'..'Z')]+[*(1..9)].map{|n|n.to_s}).instance_eval{self[rand(self.size)]}}.join

Comments on this post

peter posts on Jan 21, 2008 at 06:45
NoMethodError: private method `rand' called for #<Array:0x59c6bc>
elliottcable posts on Feb 13, 2008 at 02:30
peter, what are you on? what ruby version? that works fine for me, I'm on 1.8.6.
elliottcable posts on Feb 13, 2008 at 02:31
I just tested on 1.9, I get the same error as you. So... caveat to this snippet, it's 1.8.x and earlier only.
elliottcable posts on Feb 13, 2008 at 02:41
ah, my bad. was some library or something, who knows. I updated the snippet.
timmorgan posts on Feb 13, 2008 at 09:21
http://snippets.dzone.com/user/timmorgan/tag/random

  size = 25; (0..size).inject('') { |r, i| r << rand(93) + 33 }
mbbx6spp posts on Feb 20, 2008 at 13:02
Hopefully nobody is using the code as is above if your system/application uses this code very regularly where performance matters. For example on Ruby 1.8.6p111 on Linux (without pthreads enabled) dynamically defining the constant character array using...
[*('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.


Click here to browse all 5144 code snippets

Related Posts