turbouuid 0.0.4 → 0.0.6

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.
package/README.md CHANGED
@@ -15,16 +15,124 @@ Benchmarks ran on 1,000,000 iterations show a massive performance gain:
15
15
 
16
16
  ## Usage
17
17
 
18
- The library attaches directly to `window.turboUUID` for browser environments.
18
+ The library attaches directly to `window.randomUUID` for browser environments.
19
19
 
20
20
  ```javascript
21
21
  require('turbouuid');
22
22
 
23
23
  // Returns a standard v4-like UUID string
24
- console.log(turboUUID());
24
+ console.log(window.randomUUID());
25
25
  // Output example: f1235820-f090-3fce-a0d6-af6e26c6a0d6
26
26
  ```
27
27
 
28
+ ## SIMD-Accelerated In-Memory Storage
29
+
30
+ `turbouuid` now includes a high-performance, WebAssembly-based storage engine for managing UUIDs in memory. It leverages **128-bit SIMD** instructions to perform lightning-fast lookups and storage operations.
31
+
32
+ ![WASM Storage Demo](assets/sshot.png)
33
+
34
+ ### Key Features
35
+
36
+ * **⚡ SIMD-Powered Search**: Uses `v128` vector instructions to scan memory in parallel, offering incredibly fast `indexOf` and `has` checks.
37
+ * **🔗 Key-Ref Association**: Map each UUID to a 32-bit integer (e.g., a database ID or object reference) for efficient lookups (`uuid -> id`).
38
+ * **🧠 Zero-GC Overhead**: Operates on shared memory pages, bypassing the JavaScript garbage collector for stable, high-throughput performance.
39
+
40
+ ### API Reference
41
+
42
+ To use the storage engine, initialize it via `turboUUID.base()`:
43
+
44
+ ```javascript
45
+ const store = await turboUUID.base();
46
+ ```
47
+
48
+ #### `store.randomUUID(value: number): string`
49
+ Generates a new UUID, stores it in memory, and associates it with the given `value`. Returns the generated UUID string.
50
+
51
+ ```javascript
52
+ const uuid = store.randomUUID(12345);
53
+ ```
54
+
55
+ ---
56
+
57
+ #### `store.uuidAt(index: number): string`
58
+ Returns the UUID string stored at the specific memory index.
59
+
60
+ ```javascript
61
+ // Get the first UUID stored
62
+ const firstUUID = store.uuidAt(0);
63
+ ```
64
+
65
+ ---
66
+
67
+ #### `store.indexOf(uuid: string): number`
68
+ Returns the memory index of the given UUID. Returns `-1` if not found.
69
+ *Powered by SIMD for checking multiple bytes per cycle.*
70
+
71
+ ```javascript
72
+ const index = store.indexOf("f1235820-f090-3fce-a0d6-af6e26c6a0d6");
73
+ ```
74
+
75
+ ---
76
+
77
+ #### `store.has(uuid: string): boolean`
78
+ Checks if the UUID exists in the storage. Returns `1` (true) or `0` (false).
79
+
80
+ ```javascript
81
+ if (store.has(uuid)) {
82
+ console.log("UUID Exists!");
83
+ }
84
+ ```
85
+
86
+ ---
87
+
88
+ #### `store.valueOf(uuid: string): number`
89
+ Returns the integer value associated with the given UUID. Returns `0` if the UUID is not found.
90
+
91
+ ```javascript
92
+ const userId = store.valueOf(uuid);
93
+ console.log("User ID:", userId); // 12345
94
+ ```
95
+
96
+ ---
97
+
98
+ #### `store.setValue(uuid: string, value: number): void`
99
+ Updates or sets the integer value associated with an existing UUID. If the UUID doesn't exist, it creates a new entry.
100
+
101
+ ```javascript
102
+ // Update the ID associated with this UUID
103
+ store.setValue(uuid, 67890);
104
+ ```
105
+
106
+ ---
107
+
108
+ #### `store.remove(uuid: string): void`
109
+ Removes the UUID and its associated value from the storage.
110
+
111
+ ```javascript
112
+ store.remove(uuid);
113
+ ```
114
+
115
+ ---
116
+
117
+ #### `store.count(): number`
118
+ Returns the total number of UUIDs currently stored.
119
+
120
+ ```javascript
121
+ console.log("Total UUIDs:", store.count());
122
+ ```
123
+
124
+ ---
125
+
126
+ #### `store.forEach(callback: (uuid, value, index) => void): void`
127
+ Iterates over all stored UUIDs.
128
+ *Note: The callback receives the UUID string, the associated value, and the index.*
129
+
130
+ ```javascript
131
+ store.forEach((uuid, value, index) => {
132
+ console.log(`#${index}: ${uuid} -> ${value}`);
133
+ });
134
+ ```
135
+
28
136
  ## How It Works
29
137
 
30
138
  Instead of re-allocating memory for every generation, `turbouuid` reuses a set of TypedArrays (`Float64Array`, `Uint32Array`, `Uint16Array`, `BigUint64Array`) sharing the same buffer. This minimizes garbage collection overhead and maximizes throughput.
Binary file
package/build ADDED
@@ -0,0 +1 @@
1
+ cd src && wat4wasm --input=uuid.wat --output=../uuid.wasm --untouched-window --wat2wasm=wat2wasm --enable-threads --keep-unused-functions --enable-multi-memory
package/index.html ADDED
@@ -0,0 +1,78 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+
4
+ <head>
5
+ <script type="module">
6
+ import "./index.js"
7
+
8
+ turboUUID.base().then(base => {
9
+
10
+ const uuid = turboUUID();
11
+ const value = 2412; //integer
12
+
13
+ const setValue = base.setValue(uuid, value);
14
+ const indexOf = base.indexOf(uuid);
15
+ const uuidAt = base.uuidAt(0);
16
+ const has = !!base.has(uuid);
17
+ const count = base.count();
18
+ const valueOf = base.valueOf(uuid);
19
+ const randomUUID = base.randomUUID(value);
20
+
21
+ console.warn(base);
22
+ console.log(`const uuid = \x1b[32m"${uuid}"\x1b[0m`, ";");
23
+ console.log(`const value =`, value, ";");
24
+ console.group(`base calls:`);
25
+ console.log(`base.setValue(\x1b[34m${uuid}, ${value}\x1b[0m)`.padEnd(70).concat("-->"), setValue);
26
+ console.log(`base.indexOf(\x1b[35m${uuid}\x1b[0m)`.padEnd(70).concat("-->"), indexOf);
27
+ console.log(`base.uuidAt(\x1b[36m${indexOf}\x1b[0m)`.padEnd(70).concat("-->"), uuidAt);
28
+ console.log(`base.has(\x1b[33m${uuid}\x1b[0m)`.padEnd(70).concat("-->"), has);
29
+ console.log(`base.count(\x1b[31m\x1b[0m)`.padEnd(70).concat("-->"), count);
30
+ console.log(`base.valueOf(\x1b[31m${uuid}\x1b[0m)`.padEnd(70).concat("-->"), valueOf);
31
+ console.log(`base.randomUUID(\x1b[33m${value}\x1b[0m)`.padEnd(70).concat("-->"), randomUUID);
32
+ console.groupEnd(`base calls:`);
33
+
34
+ {
35
+ const map = new Map();
36
+ self.array = new Array();
37
+ let count, uuid, value, t0, t1, t2, dtm, dtb;
38
+
39
+ count = 4e3;
40
+ while (count--) {
41
+ uuid = turboUUID();
42
+ value = Math.floor(Math.random() * 1e5);
43
+
44
+ if (Math.random() > 0.998) {
45
+ array.push(uuid);
46
+ }
47
+
48
+ map.set(uuid, value);
49
+ base.setValue(uuid, value);
50
+ }
51
+
52
+ console.log("ready")
53
+ new BroadcastChannel("uuid").onmessage = e => {
54
+ const uuid = e.data;
55
+
56
+ t0 = performance.mark("map_start");
57
+ map.get(uuid);
58
+ dtm = performance.measure("map", "map_start");
59
+ performance.clearMarks();
60
+ performance.clearMeasures();
61
+ performance.clearResourceTimings();
62
+
63
+ t0 = performance.mark("base_start");
64
+ base.valueOf(uuid);
65
+ dtb = performance.measure("base", "base_start");
66
+ performance.clearMarks();
67
+ performance.clearMeasures();
68
+ performance.clearResourceTimings();
69
+
70
+ console.warn({ dtm, dtb })
71
+ }
72
+ }
73
+
74
+ })
75
+ </script>
76
+ </head>
77
+
78
+ </html>
package/index.js CHANGED
@@ -30,4 +30,8 @@ turboUUID.benchmark = (count = 1e6) => {
30
30
  dt = performance.now() - t0;
31
31
  console.log("window.turboUUID:\t", dt, "ms sample:", window.turboUUID());
32
32
  //window.turboUUID: 404.78500032424927 ms sample: 853dcff4-2729-3fd6-fe00-36efc5920fe0
33
- };
33
+ };
34
+
35
+ turboUUID.base = async () => {
36
+ return WebAssembly.instantiateStreaming(fetch("uuid.wasm"), self).then(i => console.log(i) || i.instance.exports);
37
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "turbouuid",
3
- "version": "0.0.4",
3
+ "version": "0.0.6",
4
4
  "description": "Fast uuid generator / an alternative for crypto.randomUUID",
5
5
  "keywords": [
6
6
  "uuid"
@@ -19,5 +19,8 @@
19
19
  "main": "index.js",
20
20
  "scripts": {
21
21
  "test": "echo \"Error: no test specified\" && exit 1"
22
+ },
23
+ "dependencies": {
24
+ "wat4wasm": "^1.1.4"
22
25
  }
23
- }
26
+ }
package/src/uuid.wat ADDED
@@ -0,0 +1,510 @@
1
+ (module
2
+ (memory $base 1 1 shared)
3
+ (memory $i8a 5000 65535 shared)
4
+ (memory $i8b 5000 65535 shared)
5
+ (memory $i16 10000 65535 shared)
6
+ (memory $i32 20000 65535 shared)
7
+ (memory $i64 40000 65535 shared)
8
+ (memory $val 20000 65535 shared)
9
+
10
+ (export "uuidAt" (func $uuidAt))
11
+ (export "valueOf" (func $valueOf))
12
+ (export "indexOf" (func $indexOf))
13
+ (export "setValue" (func $setValue))
14
+ (export "has" (func $has))
15
+ (export "count" (func $count))
16
+ (export "forEach" (func $forEach))
17
+ (export "remove" (func $remove))
18
+ (export "randomUUID" (func $randomUUID))
19
+
20
+ (global $OFFSET_UUID_COUNT i32 (i32.const 36))
21
+ (global $OFFSET_BLOCK_COUNT i32 (i32.const 44))
22
+ (global $OFFSET_SEARCH_VALUE i32 (i32.const 48))
23
+ (global $OFFSET_RANDOM_UUID i32 (i32.const 64))
24
+
25
+ (global $ARGUMENTS_REGEXP_CLEAR_STR mut ext)
26
+ (global $ARGUMENTS_REGEXP_MATCH_I8A mut ext)
27
+ (global $ARGUMENTS_REGEXP_MATCH_I8B mut ext)
28
+ (global $ARGUMENTS_REGEXP_MATCH_I16 mut ext)
29
+ (global $ARGUMENTS_REGEXP_MATCH_I32 mut ext)
30
+ (global $ARGUMENTS_REGEXP_MATCH_I64 mut ext)
31
+ (global $ARGUMENTS_REGEXP_TO_STRING mut ext)
32
+
33
+ (func $forEach
34
+ (param $callback externref)
35
+ (param $thisArg externref)
36
+ (local $iterator v128)
37
+ (local $iterated v128)
38
+
39
+ (local.set $iterator (v128.const i32x4 -1 4 1 0))
40
+ (local.set $iterated (i32x4.replace_lane 0 (local.get $iterated) (call $count)))
41
+
42
+ (loop $iteration
43
+ (if (i32x4.extract_lane 0 (local.get $iterated))
44
+ (then
45
+ (reflect $apply<ext.ext.ext>
46
+ (local.get $callback)
47
+ (local.get $thisArg)
48
+ (array $of<ext.i32.i32>ext
49
+ (call $uuidAt (i32x4.extract_lane 2 (local.get $iterated)))
50
+ (i32.load $val (i32x4.extract_lane 1 (local.get $iterated)))
51
+ (i32x4.extract_lane 2 (local.get $iterated))
52
+ )
53
+ )
54
+
55
+ (local.set $iterated
56
+ (i32x4.add (local.get $iterated) (local.get $iterator))
57
+ )
58
+
59
+ (br $iteration)
60
+ )
61
+ )
62
+ )
63
+ )
64
+
65
+ (func $store
66
+ (param $index i32)
67
+ (param $value i32)
68
+
69
+ (i32.store $val (i32.mul (i32.const 4) (local.get $index)) (local.get $value))
70
+ )
71
+
72
+ (func $load
73
+ (param $index i32)
74
+ (result i32)
75
+ (i32.load $val (i32.mul (i32.const 4) (local.get $index)))
76
+ )
77
+
78
+ (func $remove
79
+ (param $string ext)
80
+ (local $index i32)
81
+
82
+ (if (i32.eq
83
+ (i32.const -1)
84
+ (local.tee $index
85
+ (call $indexOf (local.get $string))
86
+ )
87
+ )
88
+ (then return)
89
+ )
90
+
91
+ (call $set_index_vector (local.get $index) (v128.const i64x2 0 0))
92
+ (call $store (local.get $index) (i32.const 0))
93
+ )
94
+
95
+ (func $setValue
96
+ (param $string ext)
97
+ (param $number i32)
98
+ (local $index i32)
99
+ (local $vector v128)
100
+
101
+ (local.set $vector (call $parse_vector (local.get $string)))
102
+ (local.set $index (call $get_vector_index (local.get $vector)))
103
+
104
+ (if (i32.eq (i32.const -1) (local.get $index))
105
+ (then
106
+ (call $set_index_vector
107
+ (local.tee $index (call $next_index))
108
+ (local.get $vector)
109
+ )
110
+ )
111
+ )
112
+
113
+ (call $store
114
+ (local.get $index)
115
+ (local.get $number)
116
+ )
117
+ )
118
+
119
+ (func $randomUUID
120
+ (param $number i32)
121
+ (result externref)
122
+ (call $uuidAt (call $nextIndex (local.get $number)))
123
+ )
124
+
125
+ (func $nextIndex
126
+ (param $number i32)
127
+ (result i32)
128
+ (local $index i32)
129
+
130
+ (call $store
131
+ (local.tee $index (call $new_random_index))
132
+ (local.get $number)
133
+ )
134
+
135
+ (local.get $index)
136
+ )
137
+
138
+ (func $has
139
+ (param $string ext)
140
+ (result i32)
141
+
142
+ (i32.ne (i32.const -1) (call $indexOf (local.get $string)))
143
+ )
144
+
145
+ (func $valueOf
146
+ (param $string ext)
147
+ (result i32)
148
+ (local $index i32)
149
+
150
+ (if (result i32)
151
+ (i32.ne
152
+ (i32.const -1)
153
+ (local.tee $index
154
+ (call $indexOf (local.get $string))
155
+ )
156
+ )
157
+ (then (call $load (local.get $index)))
158
+ (else (i32.const 0))
159
+ )
160
+ )
161
+
162
+ (func $count
163
+ (result i32)
164
+ (i32.load (global.get $OFFSET_UUID_COUNT))
165
+ )
166
+
167
+ (func $indexOf
168
+ (param $string externref)
169
+ (result i32)
170
+ (call $get_vector_index (call $parse_vector (local.get $string)))
171
+ )
172
+
173
+ (func $uuidAt
174
+ (param $index i32)
175
+ (result externref)
176
+ (local $offsets v128)
177
+
178
+ (local.set $offsets
179
+ (i32x4.mul
180
+ (v128.const i32x4 1 2 4 8)
181
+ (i32x4.splat (local.get $index))
182
+ )
183
+ )
184
+
185
+ (call $join_array<ext>ext
186
+ (array $of<ext.ext.ext.ext.ext>ext
187
+ (call $to_string<i32.i32>ext (i32.load8_u $i8a (i32x4.extract_lane 0 (local.get $offsets))) (i32.const 2))
188
+ (call $to_string<i32.i32>ext (i32.load8_u $i8b (i32x4.extract_lane 0 (local.get $offsets))) (i32.const 2))
189
+ (call $to_string<i32.i32>ext (i32.load16_u $i16 (i32x4.extract_lane 1 (local.get $offsets))) (i32.const 4))
190
+ (call $to_string<i32.i32>ext (i32.load $i32 (i32x4.extract_lane 2 (local.get $offsets))) (i32.const 8))
191
+ (call $to_string<i32.i64>ext (i64.load $i64 (i32x4.extract_lane 3 (local.get $offsets))) (i32.const 16))
192
+ )
193
+ )
194
+
195
+ )
196
+
197
+ (func $get_vector_index
198
+ (param $vector v128)
199
+ (result i32)
200
+
201
+ (i32.store8 $base offset=0 (global.get $OFFSET_SEARCH_VALUE) (i8x16.extract_lane_u 0 (local.get $vector)))
202
+ (i32.store8 $base offset=1 (global.get $OFFSET_SEARCH_VALUE) (i8x16.extract_lane_u 1 (local.get $vector)))
203
+ (i32.store16 $base offset=2 (global.get $OFFSET_SEARCH_VALUE) (i16x8.extract_lane_u 1 (local.get $vector)))
204
+ (i32.store $base offset=4 (global.get $OFFSET_SEARCH_VALUE) (i32x4.extract_lane 1 (local.get $vector)))
205
+ (i64.store $base offset=8 (global.get $OFFSET_SEARCH_VALUE) (i64x2.extract_lane 1 (local.get $vector)))
206
+
207
+ (call $find)
208
+ )
209
+
210
+ (func $new_random_index
211
+ (result i32)
212
+ (f64.store $base offset=0 (global.get $OFFSET_RANDOM_UUID) (call $self.Math.random<>f64))
213
+ (f64.store $base offset=8 (global.get $OFFSET_RANDOM_UUID) (call $self.Math.random<>f64))
214
+ (call $new_vector_index (v128.load $base offset=0 (global.get $OFFSET_RANDOM_UUID)))
215
+ )
216
+
217
+ (func $new_vector_index
218
+ (param $vector v128)
219
+ (result i32)
220
+ (local $index i32)
221
+
222
+ (call $set_index_vector
223
+ (local.tee $index (call $next_index))
224
+ (local.get $vector)
225
+ )
226
+
227
+ (local.get $index)
228
+ )
229
+
230
+ (func $set_index_vector
231
+ (param $index i32)
232
+ (param $vector v128)
233
+ (local $offsets v128)
234
+
235
+ (local.set $offsets
236
+ (i32x4.mul
237
+ (v128.const i32x4 1 2 4 8)
238
+ (i32x4.splat (local.get $index))
239
+ )
240
+ )
241
+
242
+ (i32.store8 $i8a (i32x4.extract_lane 0 (local.get $offsets)) (i8x16.extract_lane_u 0 (local.get $vector)))
243
+ (i32.store8 $i8b (i32x4.extract_lane 0 (local.get $offsets)) (i8x16.extract_lane_u 1 (local.get $vector)))
244
+ (i32.store16 $i16 (i32x4.extract_lane 1 (local.get $offsets)) (i16x8.extract_lane_u 1 (local.get $vector)))
245
+ (i32.store $i32 (i32x4.extract_lane 2 (local.get $offsets)) (i32x4.extract_lane 1 (local.get $vector)))
246
+ (i64.store $i64 (i32x4.extract_lane 3 (local.get $offsets)) (i64x2.extract_lane 1 (local.get $vector)))
247
+ )
248
+
249
+ (func $pad_start<ext.i32>ext
250
+ (param $string externref)
251
+ (param $padding i32)
252
+ (result externref)
253
+
254
+ (reflect $apply<ext.ext.ext>ext
255
+ (ref.extern $String:padStart)
256
+ (local.get $string)
257
+ (array $of<i32.i32>ext
258
+ (local.get $padding)
259
+ (i32.const 0)
260
+ )
261
+ )
262
+ )
263
+
264
+ (func $join_array<ext>ext
265
+ (param $array externref)
266
+ (result externref)
267
+
268
+ (reflect $apply<ext.ext.ext>ext
269
+ (ref.extern $Array:join)
270
+ (local.get $array)
271
+ (array $of<ext>ext (string))
272
+ )
273
+ )
274
+
275
+ (func $to_string<i32.i32>ext
276
+ (param $number i32)
277
+ (param $padding i32)
278
+ (result externref)
279
+
280
+ (call $pad_start<ext.i32>ext
281
+ (reflect $apply<ext.i32.ext>ext
282
+ (ref.extern $Number:toString)
283
+ (local.get $number)
284
+ (array $of<i32>ext (i32.const 16))
285
+ )
286
+ (local.get $padding)
287
+ )
288
+ )
289
+
290
+ (func $to_string<i32.i64>ext
291
+ (param $bigint i64)
292
+ (param $padding i32)
293
+ (result externref)
294
+
295
+ (call $pad_start<ext.i32>ext
296
+ (reflect $apply<ext.i64.ext>ext
297
+ (ref.extern $BigInt:toString)
298
+ (local.get $bigint)
299
+ (array $of<i32>ext (i32.const 16))
300
+ )
301
+ (local.get $padding)
302
+ )
303
+ )
304
+
305
+ (main $set_initials
306
+ (global.set $ARGUMENTS_REGEXP_CLEAR_STR (call $regexp_args (text "[^a-f0-9]") (string)))
307
+ (global.set $ARGUMENTS_REGEXP_MATCH_I8A (call $regexp_args (text "(?:[a-f0-9]{0})([a-f0-9]{2})(?:[a-f0-9]{30})") (text "0x$1")))
308
+ (global.set $ARGUMENTS_REGEXP_MATCH_I8B (call $regexp_args (text "(?:[a-f0-9]{2})([a-f0-9]{2})(?:[a-f0-9]{28})") (text "0x$1")))
309
+ (global.set $ARGUMENTS_REGEXP_MATCH_I16 (call $regexp_args (text "(?:[a-f0-9]{4})([a-f0-9]{4})(?:[a-f0-9]{24})") (text "0x$1")))
310
+ (global.set $ARGUMENTS_REGEXP_MATCH_I32 (call $regexp_args (text "(?:[a-f0-9]{8})([a-f0-9]{8})(?:[a-f0-9]{16})") (text "0x$1")))
311
+ (global.set $ARGUMENTS_REGEXP_MATCH_I64 (call $regexp_args (text "(?:[a-f0-9]{16})([a-f0-9]{16})([a-f0-9]{0}?)") (text "0x$1")))
312
+ (global.set $ARGUMENTS_REGEXP_TO_STRING (call $regexp_args (text "(.{8})(.{4})(.{4})(.{4})(.*)") (text "$1-$2-$3-$4-$5")))
313
+
314
+ (i32.store (global.get $OFFSET_UUID_COUNT) (i32.const 0))
315
+ (i32.store (global.get $OFFSET_BLOCK_COUNT) (i32.const 1))
316
+ )
317
+
318
+ (func $regexp_args
319
+ (param $expression externref)
320
+ (param $replaceWith externref)
321
+ (result externref)
322
+
323
+ (array $of<ext.ext>ext
324
+ (reflect $construct<ext.ext>ext
325
+ (ref.extern $RegExp)
326
+ (array $of<ext.ext>ext
327
+ (local.get $expression)
328
+ (text "gi")
329
+ )
330
+ )
331
+ (local.get $replaceWith)
332
+ )
333
+ )
334
+
335
+ (func $apply_regexp
336
+ (param $string externref)
337
+ (param $expargs externref)
338
+ (result externref)
339
+
340
+ (reflect $apply<ext.ext.ext>ext
341
+ (ref.extern $String:replace)
342
+ (local.get $string)
343
+ (local.get $expargs)
344
+ )
345
+ )
346
+
347
+ (func $parse_bigint
348
+ (param $string externref)
349
+ (param $expargs externref)
350
+ (result i64)
351
+
352
+ (call $self.BigInt<ext>i64
353
+ (call $apply_regexp
354
+ (local.get $string)
355
+ (local.get $expargs)
356
+ )
357
+ )
358
+ )
359
+
360
+ (func $parse_number
361
+ (param $string externref)
362
+ (param $expargs externref)
363
+ (result i32)
364
+
365
+ (call $self.Number<ext>i32
366
+ (call $apply_regexp
367
+ (local.get $string)
368
+ (local.get $expargs)
369
+ )
370
+ )
371
+ )
372
+
373
+ (func $parse_vector
374
+ (param $string externref)
375
+ (result v128)
376
+ (local $vector v128)
377
+
378
+ (local.set $string (call $apply_regexp (local.get $string) (global.get $ARGUMENTS_REGEXP_CLEAR_STR)))
379
+
380
+ (local.get $vector)
381
+ (local.tee $vector (i8x16.replace_lane 0 (call $parse_number (local.get $string) (global.get $ARGUMENTS_REGEXP_MATCH_I8A))))
382
+ (local.tee $vector (i8x16.replace_lane 1 (call $parse_number (local.get $string) (global.get $ARGUMENTS_REGEXP_MATCH_I8B))))
383
+ (local.tee $vector (i16x8.replace_lane 1 (call $parse_number (local.get $string) (global.get $ARGUMENTS_REGEXP_MATCH_I16))))
384
+ (local.tee $vector (i32x4.replace_lane 1 (call $parse_number (local.get $string) (global.get $ARGUMENTS_REGEXP_MATCH_I32))))
385
+ (local.tee $vector (i64x2.replace_lane 1 (call $parse_bigint (local.get $string) (global.get $ARGUMENTS_REGEXP_MATCH_I64))))
386
+ )
387
+
388
+ (func $next_index
389
+ (result i32)
390
+ (local $uuid.index i32)
391
+ (local.tee $uuid.index (i32.atomic.rmw.add (global.get $OFFSET_UUID_COUNT) (i32.const 1)))
392
+
393
+ (if (i32.eqz (i32.rem_u (local.get $uuid.index) (i32.const 16)))
394
+ (then (i32.atomic.rmw.add (global.get $OFFSET_BLOCK_COUNT) (i32.const 1))
395
+ (drop))
396
+ )
397
+ )
398
+
399
+ (func $find
400
+ (result i32)
401
+
402
+ (local $i8a.value i32)
403
+ (local $i8b.splat v128)
404
+ (local $i16.splat v128)
405
+ (local $i32.splat v128)
406
+ (local $i64.splat v128)
407
+
408
+ (local $offsets v128)
409
+ (local $offset.i8x16 i32)
410
+ (local $offset.i16x8 i32)
411
+ (local $offset.i32x4 i32)
412
+ (local $offset.i64x2 i32)
413
+
414
+ (local $blocks.index i32)
415
+ (local $blocks.count i32)
416
+
417
+
418
+
419
+ (local.set $i8a.value (i32.load8_u $base offset=0 (global.get $OFFSET_SEARCH_VALUE)))
420
+ (local.set $i8b.splat (v128.load8_splat $base offset=1 (global.get $OFFSET_SEARCH_VALUE)))
421
+ (local.set $i16.splat (v128.load16_splat $base offset=2 (global.get $OFFSET_SEARCH_VALUE)))
422
+ (local.set $i32.splat (v128.load32_splat $base offset=4 (global.get $OFFSET_SEARCH_VALUE)))
423
+ (local.set $i64.splat (v128.load64_splat $base offset=8 (global.get $OFFSET_SEARCH_VALUE)))
424
+
425
+ (local.set $blocks.index (i32.const 0))
426
+ (local.set $blocks.count (i32.load $base (global.get $OFFSET_BLOCK_COUNT)))
427
+
428
+ (loop $blocks
429
+ (if (local.get $blocks.count)
430
+ (then
431
+ (local.set $offsets
432
+ (i32x4.mul
433
+ (v128.const i32x4 16 32 64 128)
434
+ (i32x4.splat (local.get $blocks.index))
435
+ )
436
+ )
437
+
438
+ (local.set $offset.i8x16 (i32x4.extract_lane 0 (local.get $offsets)))
439
+ (local.set $offset.i16x8 (i32x4.extract_lane 1 (local.get $offsets)))
440
+ (local.set $offset.i32x4 (i32x4.extract_lane 2 (local.get $offsets)))
441
+ (local.set $offset.i64x2 (i32x4.extract_lane 3 (local.get $offsets)))
442
+
443
+ (local.set $blocks.index (i32.add (local.get $blocks.index) (i32.const 1)))
444
+ (local.set $blocks.count (i32.sub (local.get $blocks.count) (i32.const 1)))
445
+
446
+ (br_if $blocks (i8x16.all_true (i8x16.ne (local.get $i8b.splat) (v128.load $i8b offset=0 (local.get $offset.i8x16)))))
447
+
448
+ (if (v128.any_true (i16x8.eq (local.get $i16.splat) (v128.load $i16 offset=0 (local.get $offset.i16x8))))(then
449
+ (if (v128.any_true (i32x4.eq (local.get $i32.splat) (v128.load $i32 offset=0 (local.get $offset.i32x4))))(then
450
+ (if (v128.any_true (i64x2.eq (local.get $i64.splat) (v128.load $i64 offset=0 (local.get $offset.i64x2))))(then
451
+ (if (i32.eq (i32.load8_u $i8a offset=0 (local.get $offset.i8x16)) (local.get $i8a.value))(then
452
+ (return (i32.add (local.get $offset.i8x16) (i32.const 0)))))
453
+ (if (i32.eq (local.get $i8a.value) (i32.load8_u $i8a offset=1 (local.get $offset.i8x16)))(then
454
+ (return (i32.add (local.get $offset.i8x16) (i32.const 1)))))))
455
+
456
+ (if (v128.any_true (i64x2.eq (local.get $i64.splat) (v128.load $i64 offset=16 (local.get $offset.i64x2))))(then
457
+ (if (i32.eq (local.get $i8a.value) (i32.load8_u $i8a offset=2 (local.get $offset.i8x16)))(then
458
+ (return (i32.add (local.get $offset.i8x16) (i32.const 2)))))
459
+ (if (i32.eq (local.get $i8a.value) (i32.load8_u $i8a offset=3 (local.get $offset.i8x16)))(then
460
+ (return (i32.add (local.get $offset.i8x16) (i32.const 3)))))))))
461
+
462
+ (if (v128.any_true (i32x4.eq (local.get $i32.splat) (v128.load $i32 offset=16 (local.get $offset.i32x4))))(then
463
+ (if (v128.any_true (i64x2.eq (local.get $i64.splat) (v128.load $i64 offset=32 (local.get $offset.i64x2))))(then
464
+ (if (i32.eq (local.get $i8a.value) (i32.load8_u $i8a offset=4 (local.get $offset.i8x16)))(then
465
+ (return (i32.add (local.get $offset.i8x16) (i32.const 4)))))
466
+ (if (i32.eq (local.get $i8a.value) (i32.load8_u $i8a offset=5 (local.get $offset.i8x16)))(then
467
+ (return (i32.add (local.get $offset.i8x16) (i32.const 5)))))))
468
+
469
+ (if (v128.any_true (i64x2.eq (local.get $i64.splat) (v128.load $i64 offset=48 (local.get $offset.i64x2))))(then
470
+ (if (i32.eq (local.get $i8a.value) (i32.load8_u $i8a offset=6 (local.get $offset.i8x16)))(then
471
+ (return (i32.add (local.get $offset.i8x16) (i32.const 6)))))
472
+ (if (i32.eq (local.get $i8a.value) (i32.load8_u $i8a offset=7 (local.get $offset.i8x16)))(then
473
+ (return (i32.add (local.get $offset.i8x16) (i32.const 7)))))))))))
474
+
475
+ (if (v128.any_true (i16x8.eq (local.get $i16.splat) (v128.load $i16 offset=16 (local.get $offset.i16x8))))(then
476
+ (if (v128.any_true (i32x4.eq (local.get $i32.splat) (v128.load $i32 offset=32 (local.get $offset.i32x4))))(then
477
+ (if (v128.any_true (i64x2.eq (local.get $i64.splat) (v128.load $i64 offset=64 (local.get $offset.i64x2))))(then
478
+ (if (i32.eq (local.get $i8a.value) (i32.load8_u $i8a offset=8 (local.get $offset.i8x16)))(then
479
+ (return (i32.add (local.get $offset.i8x16) (i32.const 8)))))
480
+ (if (i32.eq (local.get $i8a.value) (i32.load8_u $i8a offset=9 (local.get $offset.i8x16)))(then
481
+ (return (i32.add (local.get $offset.i8x16) (i32.const 9)))))))
482
+
483
+ (if (v128.any_true (i64x2.eq (local.get $i64.splat) (v128.load $i64 offset=80 (local.get $offset.i64x2))))(then
484
+ (if (i32.eq (local.get $i8a.value) (i32.load8_u $i8a offset=10 (local.get $offset.i8x16)))(then
485
+ (return (i32.add (local.get $offset.i8x16) (i32.const 10)))))
486
+ (if (i32.eq (local.get $i8a.value) (i32.load8_u $i8a offset=11 (local.get $offset.i8x16)))(then
487
+ (return (i32.add (local.get $offset.i8x16) (i32.const 11)))))))))
488
+
489
+ (if (v128.any_true (i32x4.eq (local.get $i32.splat) (v128.load $i32 offset=48 (local.get $offset.i32x4))))(then
490
+ (if (v128.any_true (i64x2.eq (local.get $i64.splat) (v128.load $i64 offset=96 (local.get $offset.i64x2))))(then
491
+ (if (i32.eq (local.get $i8a.value) (i32.load8_u $i8a offset=12 (local.get $offset.i8x16)))(then
492
+ (return (i32.add (local.get $offset.i8x16) (i32.const 12)))))
493
+ (if (i32.eq (local.get $i8a.value) (i32.load8_u $i8a offset=13 (local.get $offset.i8x16)))(then
494
+ (return (i32.add (local.get $offset.i8x16) (i32.const 13)))))))
495
+
496
+ (if (v128.any_true (i64x2.eq (local.get $i64.splat) (v128.load $i64 offset=112 (local.get $offset.i64x2))))(then
497
+ (if (i32.eq (local.get $i8a.value) (i32.load8_u $i8a offset=14 (local.get $offset.i8x16)))(then
498
+ (return (i32.add (local.get $offset.i8x16) (i32.const 14)))))
499
+
500
+ (if (i32.eq (local.get $i8a.value) (i32.load8_u $i8a offset=15 (local.get $offset.i8x16)))(then
501
+ (return (i32.add (local.get $offset.i8x16) (i32.const 15)))))))))))
502
+
503
+ (br $blocks)
504
+ )
505
+ )
506
+ )
507
+
508
+ (i32.const -1)
509
+ )
510
+ )
package/test.html ADDED
@@ -0,0 +1,40 @@
1
+ <script type="module">
2
+ import "./index.js"
3
+
4
+ turboUUID.base().then(base => {
5
+ console.warn(self.base = base)
6
+
7
+ self.array = new Array();
8
+ let count, uuid, value;
9
+
10
+ count = 32768000;
11
+ while (count--) {
12
+ uuid = base.randomUUID();;
13
+ array.push(uuid);
14
+ }
15
+
16
+ console.log({ array })
17
+
18
+ console.log("ready")
19
+ new BroadcastChannel("uuid").onmessage = e => {
20
+ const uuid = e.data;
21
+ console.warn(uuid)
22
+
23
+ const t0 = performance.now();
24
+ const vm = array.indexOf(uuid);
25
+ const tm = performance.now() - t0;
26
+
27
+ const t1 = performance.now();
28
+ const vb = base.indexOf(uuid);
29
+ const tb = performance.now() - t1;
30
+
31
+ console.warn({ array: tm, vm, base: tb, vb })
32
+
33
+ performance.clearMarks();
34
+ performance.clearMeasures();
35
+ performance.clearResourceTimings();
36
+ }
37
+
38
+
39
+ })
40
+ </script>
package/uuid.wasm ADDED
Binary file