Skip to content

Instantly share code, notes, and snippets.

@jgaskins
Created November 6, 2018 04:39
Show Gist options
  • Save jgaskins/4a408897edb990b4134212790f5b9dc5 to your computer and use it in GitHub Desktop.
Save jgaskins/4a408897edb990b4134212790f5b9dc5 to your computer and use it in GitHub Desktop.
Optimizing UUID generation from strings in Crystal
require "uuid"
require "benchmark"
struct UUID
def self.optimized(value : String, variant = nil, version = nil)
bytes = uninitialized UInt8[16]
case value.size
when 36 # Hyphenated
{8, 13, 18, 23}.each do |offset|
if value[offset] != '-'
raise ArgumentError.new "Invalid UUID string format, expected hyphen at char #{offset}"
end
end
{0, 2, 4, 6, 9, 11, 14, 16, 19, 21, 24, 26, 28, 30, 32, 34}.each_with_index do |offset, i|
optimized_string_has_hex_pair_at! value, offset
bytes[i] = (value[offset].to_u8(16) * 16) + value[offset + 1].to_u8(16)
end
when 32 # Hexstring
16.times do |i|
optimized_string_has_hex_pair_at! value, i * 2
bytes[i] = (value[i * 2].to_u8(16) * 16) + value[i * 2 + 1].to_u8(16)
end
when 45 # URN
raise ArgumentError.new "Invalid URN UUID format, expected string starting with \"urn:uuid:\"" unless value.starts_with? "urn:uuid:"
{9, 11, 13, 15, 18, 20, 23, 25, 28, 30, 33, 35, 37, 39, 41, 43}.each_with_index do |offset, i|
optimized_string_has_hex_pair_at! value, offset
bytes[i] = (value[offset].to_u8(16) * 16) + value[offset + 1].to_u8(16)
end
else
raise ArgumentError.new "Invalid string length #{value.size} for UUID, expected 32 (hexstring), 36 (hyphenated) or 45 (urn)"
end
new(bytes, variant, version)
end
private def self.optimized_string_has_hex_pair_at!(value : String, i)
unless value[i].to_u8?(16) && value[i + 1].to_u8?(16)
raise ArgumentError.new [
"Invalid hex character at position #{i * 2} or #{i * 2 + 1}",
"expected '0' to '9', 'a' to 'f' or 'A' to 'F'",
].join(", ")
end
end
end
string = UUID.random.to_s
# Sanity check to ensure they're correct
puts UUID.new(string)
puts UUID.optimized(string)
Benchmark.ips do |x|
x.report("string") { UUID.new(string) }
x.report("optimized") { UUID.optimized(string) }
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment