lite-uxid 1.0.2 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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