Ruby uuid

SecureRandom.uuid helyett saját formátumú uuid kellett, pl. csak szám, és az epoch time legyen az eleje, hogy sorba rendezve látszódjon, hogy melyik lett előbb létrehozva.


# generate uuid with only numbers based on time and random numbers
# it is made sure that the time part ends with zero
# so no chance for a step back in time because of the random part
# result is minimum 20 char long (17 time and 3 random)
def get_uuid_number(len = 20)
	len = 20 if len < 20
	t = Time.now.to_f.to_s.gsub(".","")[0..16]
	r = ""; 100.times{ r << rand.to_s[2..-1]; break if r.size >= len - 17 }
	return t + "0" * (17 - t.size) + r[0..len-18]
end

get_uuid_number => "13907432579329538617"
get_uuid_number 28 => "1390743300667272050776691658"

Megjegyzés:
- az epoch time nano sec-es felbontású
- rand helyett lehet akár SecureRandom.random_number függvényt is használni
- nem sokkal lassabb a fent említett beépített megoldásnál
- sima lebegőpontos formátumú rand kimenetet használnom (a bevezető nullát és pontot elhagyva), hogy egyből kapjak több véletlen jegyet, és gyorsabb mint "rand 10000000000000000"

Hozzászólások

Próbálok még optimalizálni.

t = Time.now.to_f.to_s => "1390744427.2137268"

[26] pry(main)> Benchmark.realtime{ 100000.times{ t.gsub(".","") }}
=> 0.413758202
[27] pry(main)> Benchmark.realtime{ 100000.times{ t.gsub(".","") }}
=> 0.419834606
[28] pry(main)> Benchmark.realtime{ 100000.times{ t[0..9] << t[11..-1] }}
=> 0.071064343
[29] pry(main)> Benchmark.realtime{ 100000.times{ t[0..9] << t[11..-1] }}
=> 0.07192919

Úgyhogy a gsub-ot inkább kidobom.

Előtte:

[31] pry(main)> Benchmark.realtime{ 10000.times{ get_uuid_number }}
=> 0.194869265
[32] pry(main)> Benchmark.realtime{ 10000.times{ get_uuid_number }}
=> 0.201537085

Utána:

[38] pry(main)> Benchmark.realtime{ 10000.times{ get_uuid_number }}
=> 0.119551865
[39] pry(main)> Benchmark.realtime{ 10000.times{ get_uuid_number }}
=> 0.113414489

Majdnem dupla sebesség. Új kód:

def get_uuid_number(len = 20)
	len = 20 if len < 20
	t = Time.now.to_f.to_s
	r = ""; 100.times{ r << rand.to_s[2..-1]; break if r.size >= len-17 }
	return t[0..9] << t[11..-1] << "0" * (18 - t.size) << r[0..len-18]
end

[210] pry(main)> require "securerandom"
=> true
[211] pry(main)> Benchmark.realtime{ 10000.times{ SecureRandom.uuid }}
=> 0.119222701
[212] pry(main)> Benchmark.realtime{ 10000.times{ SecureRandom.uuid }}
=> 0.124963588
[213] pry(main)> Benchmark.realtime{ 10000.times{ get_uuid_number }}
=> 0.115556945
[214] pry(main)> Benchmark.realtime{ 10000.times{ get_uuid_number }}
=> 0.107402961