Permalink
Browse files

Switch to using Celluloid's UUID generator for speed

Thanks to @tarcieri and @mental
  • Loading branch information...
nate committed Mar 27, 2012
1 parent 6f24584 commit cbf462aa21990595fe91f8b2dbe06adccd08d3a4
Showing with 34 additions and 4 deletions.
  1. +28 −4 lib/agent/uuid.rb
  2. +6 −0 spec/uuid_spec.rb
View
@@ -1,12 +1,36 @@
require 'securerandom'
+# Borrowed from Celluloid. Using thread locals instead of extending the base
+# Thread class, though.
module Agent
module UUID
+ values = SecureRandom.hex(9).match(/(.{8})(.{4})(.{3})(.{3})/)
+ PREFIX = "#{values[1]}_#{values[2]}_4#{values[3]}_8#{values[4]}".freeze
+ BLOCK_SIZE = 0x10000
+
+ @counter = 0
+ @counter_mutex = Mutex.new
+
def self.generate
- ary = SecureRandom.random_bytes(16).unpack("NnnnnN")
- ary[2] = (ary[2] & 0x0fff) | 0x4000
- ary[3] = (ary[3] & 0x3fff) | 0x8000
- "%08x_%04x_%04x_%04x_%04x%08x" % ary
+ thread = Thread.current
+
+ unless thread[:__agent_uuid_limit__]
+ @counter_mutex.synchronize do
+ block_base = @counter
+ @counter += BLOCK_SIZE
+ thread[:__agent_uuid_counter__] = block_base
+ thread[:__agent_uuid_limit__] = @counter - 1
+ end
+ end
+
+ counter = thread[:__agent_uuid_counter__]
+ if thread[:__agent_uuid_counter__] >= thread[:__agent_uuid_limit__]
+ thread[:__agent_uuid_counter__] = thread[:__agent_uuid_limit__] = nil
+ else
+ thread[:__agent_uuid_counter__] += 1
+ end
+
+ "#{PREFIX}_#{sprintf("%012x", counter)}".freeze
end
end
end
View
@@ -4,4 +4,10 @@
it "should generate a uuid" do
Agent::UUID.generate.should match(/^[0-9a-f]{8}_[0-9a-f]{4}_[0-9a-f]{4}_[0-9a-f]{4}_[0-9a-f]{12}$/)
end
+
+ it "should generate unique IDs across the BLOCK_SIZE boundary" do
+ upper_bound = Agent::UUID::BLOCK_SIZE * 2 + 10
+ uuids = (1..upper_bound).map{ Agent::UUID.generate }
+ uuids.size.should == uuids.uniq.size
+ end
end

0 comments on commit cbf462a

Please sign in to comment.