hyperuuid-wasm 0.6.1 → 0.7.0

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: 891b6e2ed78c68a12067a1dd6e8f4ba3a7328f6ba3f5ec3853e56d7c37275baa
4
- data.tar.gz: 4252c3cee5c2654d852c3b3818b7de53cb9908ede2f30e6a530ebdaebf40cdd0
3
+ metadata.gz: a4acc2b5b222f7604e7b21efe1c5f958e7279a470f546bed3ad00089f033f13f
4
+ data.tar.gz: 0c9349c620020edf44cf37afbfff39480d49497ade4e63c94e9549e028ce2abb
5
5
  SHA512:
6
- metadata.gz: 6fda24dba0eefff039f615a7b80ba66f1948cfc4579bc96be3d81d33f015a30ea821b18ce29cf5f6c9f76f5b72b3f4e7ffa01f3f111ea9b4bd5c7f148d805055
7
- data.tar.gz: 011a274e14ea76f4ca6701ca0341c81dd2873b5b658929be8f2834832486dbf7e44312cb2f2ec6ae46da7b952d9e96e50e5c4d2785ef90c1dd32ba38e8bb9127
6
+ metadata.gz: c9f72f6b99806013e5c6557189c15f542ab1a4328528b07a2992770c01d4008111e1591b36cc00f567cdd6a919d89e6e81e7fd4bad8886bcfdcef10f7b1328c9
7
+ data.tar.gz: 6d6d7e0f7eecd6d4e62d6af9803090be5b76f90f3ee1d59534d409c92f5ee95b14d4c829af820485d3668108fbe2b500f0dc7385865de00f3a1315e225e22417
data/README.md CHANGED
@@ -123,7 +123,7 @@ bytes = HyperUuid.new_v7_batch_bytes(1000)
123
123
  first = bytes[0, 16] # ready for a BINARY(16) bind parameter
124
124
  ```
125
125
 
126
- **About 20x faster than `new_v7_batch`** for a 1000-UUID batch (10.4 µs versus 210 µs). The native call is identical — the difference is that `new_v7_batch` then allocates a `Uuid` object and its byte Strings for every item on top of it. This hands back the bytes the native core already produced, untouched.
126
+ **About 40x faster than `new_v7_batch`** for a 1000-UUID batch (4.9 µs versus 202 µs). The native call is identical — the difference is that `new_v7_batch` then allocates a `Uuid` object and its byte Strings for every item on top of it. This hands back the bytes the native core already produced, untouched.
127
127
 
128
128
  The catch, and it inverts the advice: **if you need `Uuid` objects, keep using `new_v7_batch`.** Slicing these bytes into objects yourself just relocates the identical allocations into your own code, and measures no better — sometimes worse. Reach for the byte form only when bytes are the destination: a bind parameter, a wire format, a bulk load.
129
129
 
@@ -139,30 +139,30 @@ Real numbers, `benchmark-ips` on Ruby 4.0.7, linux-x64 on an Intel Core i9-11900
139
139
 
140
140
  | Call | i/s | vs `SecureRandom.uuid` |
141
141
  |---|---:|---:|
142
- | `SecureRandom.uuid` | 872,365 | baseline |
143
- | `HyperUuid.new_v4` | 4,278,000 | **4.9x faster** |
144
- | `HyperUuid.new_v7` (explicit ms) | 3,517,000 | **4.0x faster** |
145
- | `HyperUuid.new_v6` (explicit ms) | 3,487,000 | **4.0x faster** |
146
- | `HyperUuid.new_v6` (current time) | 3,324,000 | **3.8x faster** |
147
- | `HyperUuid.new_v7` (current time) | 3,320,000 | **3.8x faster** |
148
- | `HyperUuid.new_v5` | 1,838,000 | 2.1x faster |
142
+ | `SecureRandom.uuid` | 943,917 | baseline |
143
+ | `HyperUuid.new_v4` | 5,236,000 | **5.5x faster** |
144
+ | `HyperUuid.new_v6` (explicit ms) | 3,811,000 | **4.0x faster** |
145
+ | `HyperUuid.new_v7` (explicit ms) | 3,785,000 | **4.0x faster** |
146
+ | `HyperUuid.new_v6` (current time) | 3,677,000 | **3.9x faster** |
147
+ | `HyperUuid.new_v7` (current time) | 3,574,000 | **3.8x faster** |
148
+ | `HyperUuid.new_v5` | 1,942,000 | 2.1x faster |
149
149
 
150
- A `HyperUuid.new_v4` — real entropy, correct version/variant bits, minted by the shared Rust core — costs a fifth of what `SecureRandom.uuid` does, because the Magnus extension is an ordinary native method call with nothing marshalled around it.
150
+ A `HyperUuid.new_v4` — real entropy, correct version/variant bits, minted by the shared Rust core — costs less than a fifth of what `SecureRandom.uuid` does, because the Magnus extension is an ordinary native method call with nothing marshalled around it.
151
151
 
152
152
  The "current time" rows deserve a footnote, because they will not look like this everywhere. Here they land beside the explicit-ms rows: the only difference between the two is one `Process.clock_gettime(CLOCK_REALTIME)` wall-clock read, and on this machine that read is too cheap to see. On a machine with a slow clock it is the whole story — where a virtualized clock defeats the vDSO fast path the same read costs ~1µs, which puts both current-time rows at parity with `SecureRandom.uuid` while the explicit-ms rows stay well ahead of it. `SecureRandom.uuid` never reads a clock — random v4 is the only thing it does. If your clock is slow and you are minting many, read it once and pass the timestamp, or use the batch doors.
153
153
 
154
- The Fiddle fallback (`HYPERUUID_PURE=1`, and any platform without a prebuilt extension) keeps its own diet — a reused thread-local scratch buffer instead of two GC-finalizer-registering mallocs per call, zero-copy `String` passes for read-only inputs, an unsynchronized fast path past the load mutex — landing at 1.25x slower than `SecureRandom.uuid` for v4 (1.26 µs against 1.01 µs in its own run) and 1.45x slower for v6/v7, with the same structural story as before: `Fiddle`'s interpreted marshalling is the floor, and the batch doors are how you amortize it.
154
+ The Fiddle fallback (`HYPERUUID_PURE=1`, and any platform without a prebuilt extension) keeps its own diet — a reused thread-local scratch buffer instead of two GC-finalizer-registering mallocs per call, zero-copy `String` passes for read-only inputs, an unsynchronized fast path past the load mutex — landing at 1.16x slower than `SecureRandom.uuid` for v4 (1.24 µs against 1.07 µs in its own run) and about 1.3x slower for v6/v7, with the same structural story as before: `Fiddle`'s interpreted marshalling is the floor, and the batch doors are how you amortize it.
155
155
 
156
156
  Batch generation still amortizes per-call cost on both backends — one native call for the whole batch:
157
157
 
158
158
  | Call | i/s (Magnus backend) |
159
159
  |---|---:|
160
- | `new_v6` × 1000 (individual) | 3,498 |
161
- | `new_v6_batch(1000)` | 4,633 (**1.3x**) |
162
- | `new_v7` × 1000 (individual) | 3,539 |
163
- | `new_v7_batch(1000)` | 4,677 (**1.3x**) |
160
+ | `new_v6` × 1000 (individual) | 3,761 |
161
+ | `new_v6_batch(1000)` | 4,857 (**1.3x**) |
162
+ | `new_v7` × 1000 (individual) | 3,742 |
163
+ | `new_v7_batch(1000)` | 4,850 (**1.3x**) |
164
164
 
165
- The multiplier is small on this backend for the best reason available: the individual calls are cheap, so there is little waste left to amortize, and what `new_v7_batch` spends its 214 µs on is building a thousand `Uuid` objects — the byte form above does the same native work in 10 µs. On the Fiddle backend, where each call costs 1.4 µs, the same batch is 6.7x the loop. If you need v5/v6/v7, need many at once, or need this Ruby service's IDs to agree byte-for-byte with a Go or Python service's, that's what this gem is for — and now it's the fast option too, not just the capable one.
165
+ The multiplier is small on this backend for the best reason available: the individual calls are cheap, so there is little waste left to amortize, and what `new_v7_batch` spends its 206 µs on is building a thousand `Uuid` objects — the byte form above does the same native work in 5 µs. On the Fiddle backend, where each call costs 1.4 µs, the same batch is 6.7x the loop. If you need v5/v6/v7, need many at once, or need this Ruby service's IDs to agree byte-for-byte with a Go or Python service's, that's what this gem is for — and now it's the fast option too, not just the capable one.
166
166
 
167
167
  ## Backends
168
168
 
@@ -38,6 +38,7 @@ module HyperUuid
38
38
  out = scratch
39
39
  rc = functions[:new_v4].call(out)
40
40
  raise random_source_failure("uuid_new_v4") unless rc.zero?
41
+
41
42
  out[0, 16]
42
43
  end
43
44
 
@@ -49,6 +50,7 @@ module HyperUuid
49
50
  # contract.
50
51
  rc = functions[:new_v5].call(namespace_bytes, name_bytes, name_bytes.bytesize, out)
51
52
  raise random_source_failure("uuid_new_v5") unless rc.zero?
53
+
52
54
  out[0, 16]
53
55
  end
54
56
 
@@ -68,6 +70,7 @@ module HyperUuid
68
70
 
69
71
  def new_v6_batch(count, unix_millis)
70
72
  return "" if count.zero?
73
+
71
74
  out = buffer(count * 16)
72
75
  rc = functions[:new_v6_batch].call(unix_millis, count, out)
73
76
  case rc
@@ -93,6 +96,7 @@ module HyperUuid
93
96
 
94
97
  def new_v7_batch(count, unix_millis)
95
98
  return "" if count.zero?
99
+
96
100
  out = buffer(count * 16)
97
101
  rc = functions[:new_v7_batch].call(unix_millis, count, out)
98
102
  case rc
@@ -82,7 +82,9 @@ module HyperUuid
82
82
  when 6 then Runtime.v6_unix_millis(bytes)
83
83
  when 7 then Runtime.v7_unix_millis(bytes)
84
84
  else
85
- raise ArgumentError, "timestamp is only defined for version 6 or 7 UUIDs, got version #{version}" if raise_on_mismatch
85
+ raise ArgumentError,
86
+ "timestamp is only defined for version 6 or 7 UUIDs, got version #{version}" if raise_on_mismatch
87
+
86
88
  return nil
87
89
  end
88
90
  Time.at(millis / 1000, millis % 1000, :millisecond).utc
@@ -168,6 +170,7 @@ module HyperUuid
168
170
  # Byte-order comparison against +other+, or +nil+ if +other+ isn't a Uuid.
169
171
  def <=>(other)
170
172
  return nil unless other.is_a?(Uuid)
173
+
171
174
  bytes <=> other.bytes
172
175
  end
173
176
 
data/lib/hyperuuid.rb CHANGED
@@ -18,7 +18,7 @@ require_relative "hyperuuid/runtime"
18
18
  module HyperUuid
19
19
  # This gem's own version — distinct from the RFC 9562 UUID *versions* (v4/v5/v6/v7) the
20
20
  # rest of this module generates.
21
- VERSION = "0.6.1"
21
+ VERSION = "0.7.0"
22
22
 
23
23
  # The widest batch count, and the longest v5 name in bytes, the native ABI carries (a u32).
24
24
  # (The millisecond count is a u64; unix_millis_from refuses anything wider.)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hyperuuid-wasm
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.1
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brian Buvinghausen