lite-uxid 1.0.2 → 1.0.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3a8f42192c67ad0638ff6b3001a5887b5c5fc1bd9e05cb7e6a757c53d11ce15d
4
- data.tar.gz: '058af68572f76f3c6227f2a437e254b25e783e9495e86bddd57b5bf2295b5446'
3
+ metadata.gz: f097d6940ba5a48c1e0abc585373595a1445cca093efb20f8e1043a1d68befb0
4
+ data.tar.gz: 55883b58633a5cdf3e01e5cd85d3c8ede048b43ac73c3fa7706e49ddf81c816d
5
5
  SHA512:
6
- metadata.gz: c29f1a9f5cd7721cf67f07b5f4077ed1e0aa312bcf7fa095ebaf4a51d4c0ec4b518ab719bd32b3ece0f431c248f1f27ef3aaeb2f60f99d6f197dba8375248539
7
- data.tar.gz: d476f672216ee1ee7e136ffe1dd335c3a6ebd15ab29a7ade8d7f1fed7e74416fd3109067d5e1af6ce70fea240b11c6af4a88d59c7f8fed81d620d72178dbd281
6
+ metadata.gz: f0a0f82a7509fb845d5a86c0f52fe8ce7138fa602203dc7a0296d98325787e8f9aa2feecfb2edd839ef41605d23e81d6072b36e53c27d3fb0ef47f5a172fcc82
7
+ data.tar.gz: 85bda358c26cd64b5a9b2d1e994543eca653250748a4df35a22428daf973041dc63654ac5fd7d046108248c7da61727ca579b9ace9b2556c5d014a4f0c85ac90
data/.rubocop.yml CHANGED
@@ -18,6 +18,8 @@ Metrics/BlockLength:
18
18
  Exclude:
19
19
  - 'spec/**/**/*'
20
20
  - '*.gemspec'
21
+ RSpec/MultipleExpectations:
22
+ Enabled: false
21
23
  Style/Documentation:
22
24
  Enabled: false
23
25
  Style/ExpandPathArguments:
data/CHANGELOG.md CHANGED
@@ -6,6 +6,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [1.0.3] - 2019-07-31
10
+ ### Added
11
+ - Added benchmarks
12
+ ### Changed
13
+ - Changed instance method names to match class names
14
+ - Changed nanoid encoder to be faster
15
+ - Changed ulid encoder to be faster
16
+
9
17
  ## [1.0.2] - 2019-07-30
10
18
  ### Added
11
19
  - Added nanoid
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- lite-uxid (1.0.2)
4
+ lite-uxid (1.0.3)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
data/README.md CHANGED
@@ -31,6 +31,7 @@ Or install it yourself as:
31
31
  * [NanoID](#nanoid)
32
32
  * [ULID](#ulid)
33
33
  * [ActiveRecord](#active_record)
34
+ * [Benchmarks](#benchmarks)
34
35
  * [Port](#port)
35
36
 
36
37
  ## Configuration
@@ -48,7 +49,7 @@ end
48
49
 
49
50
  ## Hash
50
51
 
51
- Hash ID's are reversible but less performant than ULID.
52
+ Hash ID's are reversible and is the most performant generator.
52
53
 
53
54
  ```ruby
54
55
  Lite::Uxid::Hash.encode(10) #=> 'q5D8inm0'
@@ -57,7 +58,7 @@ Lite::Uxid::Hash.decode('q5D8inm0') #=> 10
57
58
 
58
59
  ## NanoID
59
60
 
60
- NanoID are not reversible and are the most performant random ID's but while unlikely can produce collisions.
61
+ NanoID are not reversible and are the second fastest ID generator but while unlikely can produce collisions.
61
62
 
62
63
  ```ruby
63
64
  Lite::Uxid::Nanoid.encode #=> '0bmHjB5Gx8FTBqJekX6dS6XIXf'
@@ -65,7 +66,7 @@ Lite::Uxid::Nanoid.encode #=> '0bmHjB5Gx8FTBqJekX6dS6XIXf'
65
66
 
66
67
  ## ULID
67
68
 
68
- ULID are not reversible and more performant than Hash ID's.
69
+ ULID are not reversible but provide information outside of just randomness.
69
70
 
70
71
  ```ruby
71
72
  Lite::Uxid::Ulid.encode #=> '1mqfg9qa96s8s5f02o1ucf8lcc'
@@ -113,6 +114,12 @@ user = User.new
113
114
  user.hash_to_id #=> Decodes the records uxid to id (only for Hash based Id's)
114
115
  ```
115
116
 
117
+ ## Benchmarks
118
+
119
+ The classes ranked from fastest to slowest are `Hash`, `Nanoid`, and `Ulid`.
120
+
121
+ View how each compares by running the [benchmarks](https://github.com/drexed/lite-uxid/tree/master/benchmarks).
122
+
116
123
  ## Port
117
124
 
118
125
  `Lite::Uxid` is a compatible port of [ActiveUxid](https://github.com/drexed/active_uxid).
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ %w[lib benchmarks].each { |name| $LOAD_PATH.unshift(name) }
4
+
5
+ require 'benchmark/ips'
6
+ require 'lite/uxid'
7
+
8
+ Benchmark.ips do |x|
9
+ x.report('Hash') do
10
+ Lite::Uxid::Hash.encode(rand(1..1_000_000))
11
+ end
12
+
13
+ x.report('NanoID') do
14
+ Lite::Uxid::Nanoid.encode
15
+ end
16
+
17
+ x.report('ULID') do
18
+ Lite::Uxid::Ulid.encode
19
+ end
20
+
21
+ x.compare!
22
+ end
@@ -13,25 +13,27 @@ module Lite
13
13
 
14
14
  def encode(id)
15
15
  klass = new(id)
16
- klass.encode_uxid
16
+ klass.encode
17
17
  end
18
18
 
19
- end
19
+ def decode(id)
20
+ klass = new(id)
21
+ klass.decode
22
+ end
20
23
 
21
- def self.decode(id)
22
- klass = new(id)
23
- klass.decode_uxid
24
24
  end
25
25
 
26
- def encode_uxid
27
- uxid_encode_chars((@id + encoding_salt) << encoding_length)
26
+ def encode
27
+ encode_chars((@id + encoding_salt) << encoding_length)
28
28
  end
29
29
 
30
- def decode_uxid
31
- (uxid_decode_chars(@id) >> encoding_length) - encoding_salt
30
+ def decode
31
+ (decode_chars(@id) >> encoding_length) - encoding_salt
32
32
  end
33
33
 
34
- def uxid_encode_chars(id)
34
+ private
35
+
36
+ def encode_chars(id)
35
37
  return '0' if id.zero?
36
38
  return nil if id.negative?
37
39
 
@@ -45,7 +47,7 @@ module Lite
45
47
  str
46
48
  end
47
49
 
48
- def uxid_decode_chars(id)
50
+ def decode_chars(id)
49
51
  pos = 0
50
52
  num = 0
51
53
  len = id.length
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'securerandom'
4
-
5
3
  module Lite
6
4
  module Uxid
7
5
  class Nanoid < Lite::Uxid::Base
@@ -10,15 +8,22 @@ module Lite
10
8
 
11
9
  def encode
12
10
  klass = new
13
- klass.nanoid_encode
11
+ klass.encode
14
12
  end
15
13
 
16
14
  end
17
15
 
18
- def nanoid_encode
19
- encoding_length.times.with_object('') do |_i, str|
20
- str + encoding_chars[(SecureRandom.rand * encoding_base).floor]
16
+ def encode
17
+ str = ''
18
+ len = encoding_length
19
+ chars = encoding_chars.split(str)
20
+
21
+ while len.positive?
22
+ str += chars.sample
23
+ len -= 1
21
24
  end
25
+
26
+ str
22
27
  end
23
28
 
24
29
  end
@@ -12,13 +12,15 @@ module Lite
12
12
 
13
13
  included do
14
14
  after_create :callback_generate_uxid!, if: proc { respond_to?(:uxid) }
15
+ end
15
16
 
16
- def self.find_by_uxid(uxid)
17
+ class_methods do
18
+ def find_by_uxid(uxid)
17
19
  decoded_id = Lite::Uxid::Hash.decode(uxid)
18
20
  find_by(id: decoded_id)
19
21
  end
20
22
 
21
- def self.find_by_uxid!(uxid)
23
+ def find_by_uxid!(uxid)
22
24
  record = find_by_uxid(uxid)
23
25
  return record unless record.nil?
24
26
 
@@ -12,12 +12,14 @@ module Lite
12
12
 
13
13
  included do
14
14
  before_create :callback_generate_uxid!, if: proc { respond_to?(:uxid) }
15
+ end
15
16
 
16
- def self.find_by_uxid(uxid)
17
+ class_methods do
18
+ def find_by_uxid(uxid)
17
19
  find_by(uxid: uxid)
18
20
  end
19
21
 
20
- def self.find_by_uxid!(uxid)
22
+ def find_by_uxid!(uxid)
21
23
  record = find_by_uxid(uxid)
22
24
  return record unless record.nil?
23
25
 
@@ -12,12 +12,14 @@ module Lite
12
12
 
13
13
  included do
14
14
  before_create :callback_generate_uxid!, if: proc { respond_to?(:uxid) }
15
+ end
15
16
 
16
- def self.find_by_uxid(uxid)
17
+ class_methods do
18
+ def find_by_uxid(uxid)
17
19
  find_by(uxid: uxid)
18
20
  end
19
21
 
20
- def self.find_by_uxid!(uxid)
22
+ def find_by_uxid!(uxid)
21
23
  record = find_by_uxid(uxid)
22
24
  return record unless record.nil?
23
25
 
@@ -6,38 +6,49 @@ module Lite
6
6
  module Uxid
7
7
  class Ulid < Lite::Uxid::Base
8
8
 
9
+ MASK ||= 0x1f
10
+
9
11
  class << self
10
12
 
11
13
  def encode
12
14
  klass = new
13
- klass.uxid_encode
15
+ klass.encode
14
16
  end
15
17
 
16
18
  end
17
19
 
18
- def uxid_encode
19
- (1..encoding_length).reduce('') do |str, num|
20
- shift = 128 - 5 * num
21
- "#{str}#{encoding_chars[(uxid_octect >> shift) & 0x1f]}"
20
+ def encode
21
+ oct = octect
22
+ ele = '0' * encoding_length
23
+ pos = encoding_length - 1
24
+
25
+ while oct.positive?
26
+ ele[pos] = encoding_chars[oct & MASK]
27
+ oct >>= 5
28
+ pos -= 1
22
29
  end
30
+
31
+ ele
23
32
  end
24
33
 
25
- def uxid_bytes
26
- "#{uxid_unixtime_48bit}#{SecureRandom.random_bytes(10)}"
34
+ private
35
+
36
+ def bytes
37
+ "#{unixtime_48bit}#{SecureRandom.random_bytes(10)}"
27
38
  end
28
39
 
29
- def uxid_octect
30
- (hi, lo) = uxid_bytes.unpack('Q>Q>')
40
+ def octect
41
+ (hi, lo) = bytes.unpack('Q>Q>')
31
42
  (hi << 64) | lo
32
43
  end
33
44
 
34
- def uxid_unixtime_flex
45
+ def unixtime_ms
35
46
  time = Time.respond_to?(:current) ? Time.current : Time.now
36
- (time.to_f * 10_000).to_i
47
+ (time.to_f * 1_000).to_i
37
48
  end
38
49
 
39
- def uxid_unixtime_48bit
40
- [uxid_unixtime_flex].pack('Q>')[2..-1]
50
+ def unixtime_48bit
51
+ [unixtime_ms].pack('Q>')[2..-1]
41
52
  end
42
53
 
43
54
  end
@@ -3,7 +3,7 @@
3
3
  module Lite
4
4
  module Uxid
5
5
 
6
- VERSION ||= '1.0.2'
6
+ VERSION ||= '1.0.3'
7
7
 
8
8
  end
9
9
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lite-uxid
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Juan Gomez
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-07-30 00:00:00.000000000 Z
11
+ date: 2019-07-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -184,6 +184,7 @@ files:
184
184
  - README.md
185
185
  - Rakefile
186
186
  - _config.yml
187
+ - benchmarks/compare.rb
187
188
  - bin/console
188
189
  - bin/setup
189
190
  - lib/generators/lite/uxid/install_generator.rb