@cdlab996/genid 1.2.1 → 1.4.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.
package/README.md CHANGED
@@ -1,354 +1,377 @@
1
1
  # @cdlab996/genid
2
2
 
3
- 基于 Snowflake 算法的高性能分布式唯一 ID 生成器,支持漂移算法和时钟回拨处理,适用于分布式系统中的唯一标识生成需求。
3
+ [![npm version](https://img.shields.io/npm/v/@cdlab996/genid)](https://www.npmjs.com/package/@cdlab996/genid)
4
+ [![license](https://img.shields.io/npm/l/@cdlab996/genid)](./LICENSE)
4
5
 
5
- ## 特性
6
+ High-performance distributed unique ID generator based on the Snowflake algorithm, with drift mode and clock-rollback handling.
6
7
 
7
- - 🚀 **漂移算法**:高并发场景下性能优异
8
- - 🔄 **时钟回拨处理**:优雅处理时钟回拨,不阻塞 ID 生成
9
- - ⚙️ **灵活配置**:支持自定义位长度分配
10
- - 📊 **性能监控**:内置统计和调试功能
11
- - ✅ **ID 验证**:验证 ID 的有效性,支持严格/宽松模式
8
+ [中文文档](./README.zh-CN.md)
12
9
 
13
- ## 架构设计
10
+ ## Features
14
11
 
15
- ### 核心流程
12
+ - **Drift Algorithm** - Exceeds per-millisecond sequence limits under high concurrency for better throughput
13
+ - **Clock Rollback Handling** - Graceful degradation using reserved sequence numbers without blocking ID generation
14
+ - **Flexible Configuration** - Customize bit allocation for timestamp, worker ID, and sequence
15
+ - **ID Validation** - Strict and loose validation modes with `afterTime` support
16
+ - **Runtime Monitoring** - Built-in statistics, parsing, and binary formatting for debugging
16
17
 
17
- ```mermaid
18
- graph TB
19
- A[开始生成 ID] --> B{是否处于漂移状态?}
20
-
21
- B -->|否| C[正常路径]
22
- B -->|是| D[漂移路径]
23
-
24
- C --> E{检测时钟}
25
- E -->|时钟回拨| F[使用保留序列号 0-4]
26
- E -->|时间前进| G[重置序列号]
27
- E -->|同一毫秒| H{序列号是否溢出?}
28
-
29
- H -->|否| I[序列号+1 正常生成]
30
- H -->|是| J[进入漂移状态 时间戳+1]
31
-
32
- D --> K{检测时间}
33
- K -->|时间追上| L[退出漂移 恢复正常]
34
- K -->|超过最大漂移| M[等待下一毫秒 退出漂移]
35
- K -->|继续漂移| N{序列号是否溢出?}
36
-
37
- N -->|否| O[使用当前序列号]
38
- N -->|是| P[时间戳+1 重置序列号]
39
-
40
- F --> Q[计算 ID]
41
- G --> Q
42
- I --> Q
43
- J --> Q
44
- L --> Q
45
- M --> Q
46
- O --> Q
47
- P --> Q
48
-
49
- Q --> R[更新统计]
50
- R --> S[返回 ID]
51
- ```
18
+ ## Installation
52
19
 
53
- ### ID 结构(64-bit)
20
+ ```bash
21
+ # npm
22
+ npm install @cdlab996/genid
54
23
 
24
+ # pnpm
25
+ pnpm add @cdlab996/genid
55
26
  ```
56
- |------------ 时间戳 ------------|-- 工作节点 ID --|-- 序列号 --|
57
- 42-52 bits 1-15 bits 3-21 bits
58
- ```
59
-
60
- **位分配示例(默认配置):**
61
-
62
- - 时间戳:52 bits(可用约 139 年)
63
- - 工作节点 ID:6 bits(支持 64 个节点)
64
- - 序列号:6 bits(每毫秒 59 个 ID,5-63)
65
-
66
- **序列号分配:**
67
-
68
- - `0-4`:保留用于时钟回拨
69
- - `5-maxSeqNumber`:正常使用
70
27
 
71
- ## 快速开始
28
+ ## Quick Start
72
29
 
73
30
  ```typescript
74
31
  import { GenidOptimized } from '@cdlab996/genid'
75
32
 
76
- // 创建实例(每个 Worker/进程使用不同的 workerId
33
+ // Create an instance (use a different workerId for each worker/process)
77
34
  const genid = new GenidOptimized({ workerId: 1 })
78
35
 
79
- // 生成 ID
80
- const id = genid.nextId()
81
- console.log(id) // 123456789012345
82
- ```
83
-
84
- ## API 参考
85
-
86
- ### 构造函数
87
-
88
- ```typescript
89
- new GenidOptimized(options: GenidOptions)
90
- ```
91
-
92
- **配置选项**
93
-
94
- | 参数 | 类型 | 必填 | 默认值 | 说明 |
95
- |------|------|------|--------|------|
96
- | `workerId` | number | ✅ | - | 工作节点 ID(范围:0 到 2^workerIdBitLength-1) |
97
- | `method` | GenidMethod | ❌ | `DRIFT` | 算法类型:`DRIFT` 或 `TRADITIONAL` |
98
- | `baseTime` | number | ❌ | `1577836800000` | 起始时间戳(毫秒,默认:2020-01-01) |
99
- | `workerIdBitLength` | number | ❌ | `6` | 工作节点 ID 位数(1-15) |
100
- | `seqBitLength` | number | ❌ | `6` | 序列号位数(3-21) |
101
- | `maxSeqNumber` | number | ❌ | `2^seqBitLength-1` | 最大序列号 |
102
- | `minSeqNumber` | number | ❌ | `5` | 最小序列号(0-4 保留用于时钟回拨) |
103
- | `topOverCostCount` | number | ❌ | `2000` | 最大漂移次数 |
104
-
105
- ### 生成 ID
106
-
107
- #### `nextId()`
108
-
109
- 返回 Number 或 BigInt 类型的 ID(自动选择)
110
-
111
- ```typescript
36
+ // Generate an ID
112
37
  const id = genid.nextId()
113
- ```
114
38
 
115
- #### `nextNumber()`
39
+ // Batch generate
40
+ const ids = genid.nextBatch(1000)
116
41
 
117
- 返回 Number 类型的 ID(超出安全范围会抛出错误)
42
+ // Parse an ID
43
+ const info = genid.parse(id)
44
+ // => { timestamp: Date, timestampMs: 1609459200000, workerId: 1, sequence: 42 }
118
45
 
119
- ```typescript
120
- const id = genid.nextNumber()
46
+ // Validate an ID
47
+ genid.isValid(id) // true
121
48
  ```
122
49
 
123
- #### `nextBigId()`
124
-
125
- 返回 BigInt 类型的 ID
50
+ ## API
126
51
 
127
- ```typescript
128
- const id = genid.nextBigId()
129
- ```
52
+ ### `new GenidOptimized(options)`
130
53
 
131
- #### `nextBatch(count, asBigInt?)`
54
+ | Parameter | Type | Required | Default | Description |
55
+ | ------------------- | ------------- | :------: | ------------------ | --------------------------------------------------- |
56
+ | `workerId` | `number` | Yes | - | Worker node ID (0 to 2^workerIdBitLength-1) |
57
+ | `method` | `GenidMethod` | | `DRIFT` | Algorithm: `DRIFT` or `TRADITIONAL` |
58
+ | `baseTime` | `number` | | `1577836800000` | Base timestamp in ms (default: 2020-01-01) |
59
+ | `workerIdBitLength` | `number` | | `6` | Bit length for worker ID (1-15) |
60
+ | `seqBitLength` | `number` | | `6` | Bit length for sequence (3-21) |
61
+ | `maxSeqNumber` | `number` | | `2^seqBitLength-1` | Maximum sequence number |
62
+ | `minSeqNumber` | `number` | | `5` | Minimum sequence number (0-4 reserved for rollback) |
63
+ | `topOverCostCount` | `number` | | `2000` | Maximum drift count |
132
64
 
133
- 批量生成 ID
65
+ ### Generating IDs
134
66
 
135
67
  ```typescript
136
- const ids = genid.nextBatch(100) // 生成 100 ID
137
- const bigIds = genid.nextBatch(100, true) // 生成 100 BigInt ID
68
+ genid.nextId() // Returns number | bigint (auto-selects)
69
+ genid.nextNumber() // Returns number (throws if exceeds safe integer range)
70
+ genid.nextBigId() // Returns bigint
71
+ genid.nextBatch(100) // Batch generate 100 IDs
72
+ genid.nextBatch(100, true) // Batch generate 100 BigInt IDs
138
73
  ```
139
74
 
140
- ### 解析 ID
141
-
142
- #### `parse(id)`
143
-
144
- 解析 ID,提取组成部分
75
+ ### Parsing & Validation
145
76
 
146
77
  ```typescript
147
- const info = genid.parse(id)
148
- console.log(info)
149
- // {
150
- // timestamp: Date, // 生成时间
151
- // timestampMs: 1609459200000,
152
- // workerId: 1, // 工作节点 ID
153
- // sequence: 42 // 序列号
154
- // }
78
+ // Parse an ID into its components
79
+ genid.parse(id)
80
+ // => { timestamp: Date, timestampMs: number, workerId: number, sequence: number }
81
+
82
+ // Loose validation: checks structural validity
83
+ genid.isValid(id) // true
84
+ genid.isValid('invalid') // false
85
+
86
+ // Strict validation: requires workerId to match the current instance
87
+ genid.isValid(id, true) // true (generated by this instance)
88
+ genid.isValid(otherId, true) // false (generated by another instance)
89
+
90
+ // Time-bound validation: reject IDs generated before a given time
91
+ const startupTime = Date.now()
92
+ genid.isValid(id, { afterTime: startupTime }) // true
93
+ genid.isValid(id, { strictWorkerId: true, afterTime: startupTime }) // combined
155
94
  ```
156
95
 
157
- ### 验证 ID
158
-
159
- #### `isValid(id, strictWorkerId?)`
160
-
161
- 验证 ID 是否为有效的 Snowflake ID
162
-
163
- **参数**
164
- - `id` - 要验证的 ID(支持 Number、BigInt、String 类型)
165
- - `strictWorkerId` - 可选,是否严格验证 workerId 必须匹配当前实例(默认:false)
166
-
167
- **返回值**
168
- - `boolean` - ID 是否有效
169
-
170
- **验证规则**
171
- - ✅ ID 为正数
172
- - ✅ ID 在 64 位范围内
173
- - ✅ 时间戳在合理范围内(>= baseTime,<= 当前时间 + 1秒容差)
174
- - ✅ workerId 在有效范围内(0 到 2^workerIdBitLength-1)
175
- - ✅ 序列号在有效范围内(0 到 2^seqBitLength-1)
176
- - ✅ 严格模式下:workerId 必须匹配当前实例
177
-
178
- ```typescript
179
- const genid = new GenidOptimized({ workerId: 1 })
180
- const id = genid.nextId()
181
-
182
- // 宽松模式:验证 ID 格式是否有效
183
- genid.isValid(id) // true
184
- genid.isValid(12345) // false(无效的 ID)
185
- genid.isValid(-1) // false(负数)
186
- genid.isValid('invalid') // false(无效格式)
187
-
188
- // 严格模式:验证 ID 是否由当前实例生成
189
- const genid2 = new GenidOptimized({ workerId: 2 })
190
- const id2 = genid2.nextId()
191
-
192
- genid.isValid(id2) // true(宽松模式,其他实例的 ID 也有效)
193
- genid.isValid(id2, true) // false(严格模式,workerId 不匹配)
194
- genid.isValid(id, true) // true(严格模式,workerId 匹配)
195
- ```
196
-
197
- ### 统计与配置
198
-
199
- #### `getStats()`
200
-
201
- 获取生成器统计信息
96
+ ### Statistics & Configuration
202
97
 
203
98
  ```typescript
204
- const stats = genid.getStats()
205
- // {
206
- // totalGenerated: 1000, // 总生成数量
207
- // overCostCount: 10, // 漂移次数
208
- // turnBackCount: 2, // 时钟回拨次数
209
- // uptimeMs: 60000, // 运行时间
210
- // avgPerSecond: 16, // 每秒平均生成量
211
- // currentState: 'NORMAL' // 当前状态
99
+ // Get runtime statistics
100
+ genid.getStats()
101
+ // => {
102
+ // totalGenerated: 1000,
103
+ // overCostCount: 10,
104
+ // turnBackCount: 2,
105
+ // uptimeMs: 60000,
106
+ // avgPerSecond: 16,
107
+ // currentState: 'NORMAL' | 'OVER_COST'
212
108
  // }
213
- ```
214
-
215
- #### `getConfig()`
216
109
 
217
- 获取配置信息
218
-
219
- ```typescript
220
- const config = genid.getConfig()
221
- // {
110
+ // Get current configuration
111
+ genid.getConfig()
112
+ // => {
222
113
  // method: 'DRIFT',
223
114
  // workerId: 1,
224
115
  // workerIdRange: '0-63',
225
116
  // sequenceRange: '5-63',
117
+ // maxSequence: 63,
226
118
  // idsPerMillisecond: 59,
227
119
  // baseTime: Date,
228
120
  // timestampBits: 52,
229
121
  // workerIdBits: 6,
230
122
  // sequenceBits: 6
231
123
  // }
232
- ```
233
-
234
- #### `resetStats()`
235
124
 
236
- 重置统计数据
237
-
238
- ```typescript
125
+ // Reset statistics
239
126
  genid.resetStats()
240
127
  ```
241
128
 
242
- ### 调试工具
243
-
244
- #### `formatBinary(id)`
245
-
246
- 格式化 ID 为二进制字符串
129
+ ### Debugging
247
130
 
248
131
  ```typescript
249
- console.log(genid.formatBinary(id))
132
+ genid.formatBinary(id)
250
133
  // ID: 123456789012345
251
134
  // Binary (64-bit):
252
- // 0000000000011010... - 时间戳 (52 bits) = 2025-10-17T...
253
- // 000001 - 工作节点 ID (6 bits) = 1
254
- // 101010 - 序列号 (6 bits) = 42
135
+ // 0000000000011010... - Timestamp (52 bits) = 2025-10-17T...
136
+ // 000001 - Worker ID (6 bits) = 1
137
+ // 101010 - Sequence (6 bits) = 42
255
138
  ```
256
139
 
257
- ## 使用示例
140
+ ## Examples
258
141
 
259
- ### 基础用法
142
+ ### Custom Bit Allocation
260
143
 
261
144
  ```typescript
262
- const genid = new GenidOptimized({
263
- workerId: 1
264
- })
265
-
266
- // 生成单个 ID
267
- const id1 = genid.nextId()
268
-
269
- // 批量生成
270
- const ids = genid.nextBatch(1000)
271
- ```
145
+ import { GenidOptimized, GenidMethod } from '@cdlab996/genid'
272
146
 
273
- ### 自定义配置
274
-
275
- ```typescript
276
147
  const genid = new GenidOptimized({
277
148
  workerId: 1,
278
149
  method: GenidMethod.TRADITIONAL,
279
150
  baseTime: new Date('2024-01-01').valueOf(),
280
- workerIdBitLength: 10, // 支持 1024 个节点
281
- seqBitLength: 12, // 每毫秒 4096 ID
282
- topOverCostCount: 5000
151
+ workerIdBitLength: 10, // Support 1024 nodes
152
+ seqBitLength: 12, // 4096 IDs per millisecond
153
+ topOverCostCount: 5000,
283
154
  })
284
155
  ```
285
156
 
286
- ### 验证 ID
157
+ ### Validating External IDs
287
158
 
288
159
  ```typescript
289
- const genid = new GenidOptimized({ workerId: 1 })
290
-
291
- // 生成并验证 ID
292
- const id = genid.nextId()
293
- if (genid.isValid(id)) {
294
- console.log('ID 有效')
295
- }
296
-
297
- // 验证外部 ID(例如从数据库或 API 获取的 ID)
160
+ // Validate IDs from a database or API
298
161
  const externalId = '123456789012345'
299
162
  if (genid.isValid(externalId)) {
300
163
  const info = genid.parse(externalId)
301
- console.log('ID 有效,解析结果:', info)
164
+ console.log('Generated at:', info.timestamp)
165
+ console.log('From worker:', info.workerId)
302
166
  } else {
303
- console.error('ID 无效')
167
+ console.error('Invalid ID')
304
168
  }
305
-
306
- // 严格验证(只接受当前实例生成的 ID)
307
- const isMyId = genid.isValid(id, true)
308
169
  ```
309
170
 
310
- ### 监控性能
171
+ ### Performance Monitoring
311
172
 
312
173
  ```typescript
313
- // 定期检查统计信息
314
174
  setInterval(() => {
315
175
  const stats = genid.getStats()
316
- console.log(`生成速率: ${stats.avgPerSecond} ID/秒`)
317
- console.log(`漂移次数: ${stats.overCostCount}`)
176
+ console.log(`Rate: ${stats.avgPerSecond} ID/s | Drift: ${stats.overCostCount} | Rollback: ${stats.turnBackCount}`)
318
177
  }, 10000)
319
178
  ```
320
179
 
321
- ## 算法模式
180
+ ## Algorithm Modes
181
+
182
+ | Mode | Description | Use Case |
183
+ | ------------------- | ------------------------------------------------------------------ | ----------------------------- |
184
+ | **DRIFT** (default) | Borrows future timestamps when sequence is exhausted; avoids waits | High-frequency ID generation |
185
+ | **TRADITIONAL** | Strictly increasing timestamps; waits for next ms on exhaustion | Strict time-ordering required |
186
+
187
+ ## Architecture
188
+
189
+ ### ID Structure (64-bit)
190
+
191
+ ```
192
+ |------------ Timestamp ------------|-- Worker ID --|-- Sequence --|
193
+ 42-52 bits 1-15 bits 3-21 bits
194
+ ```
195
+
196
+ Default: Timestamp 52 bits (~139 years) | Worker ID 6 bits (64 nodes) | Sequence 6 bits (59 IDs/ms)
197
+
198
+ Sequence values `0-4` are reserved for clock rollback; normal generation starts at `5`.
199
+
200
+ ### Core Flow
201
+
202
+ ```mermaid
203
+ graph TB
204
+ A[Start ID Generation] --> B{In drift mode?}
322
205
 
323
- ### DRIFT(漂移模式,推荐)
206
+ B -->|No| C[Normal Path]
207
+ B -->|Yes| D[Drift Path]
324
208
 
325
- - 高并发下性能更好
326
- - 允许时间戳漂移以避免等待
327
- - 适合高频 ID 生成场景
209
+ C --> E{Check Clock}
210
+ E -->|Clock Rollback| F[Use Reserved Sequence 0-4]
211
+ E -->|Time Advanced| G[Reset Sequence]
212
+ E -->|Same Millisecond| H{Sequence Exhausted?}
328
213
 
329
- ### TRADITIONAL(传统模式)
214
+ H -->|No| I[Increment Sequence]
215
+ H -->|Yes| J[Enter Drift Mode, Timestamp+1]
330
216
 
331
- - 严格按时间戳递增
332
- - 序列号耗尽时等待下一毫秒
333
- - 适合对时间顺序要求严格的场景
217
+ D --> K{Check Time}
218
+ K -->|Time Caught Up| L[Exit Drift, Resume Normal]
219
+ K -->|Exceeded Max Drift| M[Wait for Next ms, Exit Drift]
220
+ K -->|Continue Drift| N{Sequence Exhausted?}
334
221
 
335
- ## 注意事项
222
+ N -->|No| O[Use Current Sequence]
223
+ N -->|Yes| P[Timestamp+1, Reset Sequence]
336
224
 
337
- ⚠️ **重要提示**
225
+ F --> Q[Assemble ID]
226
+ G --> Q
227
+ I --> Q
228
+ J --> Q
229
+ L --> Q
230
+ M --> Q
231
+ O --> Q
232
+ P --> Q
233
+
234
+ Q --> R[Update Statistics]
235
+ R --> S[Return ID]
236
+ ```
338
237
 
339
- - 每个 Worker/进程必须使用**不同的 workerId**
340
- - 实例**不是线程安全的**,不要跨线程共享
341
- - `workerIdBitLength + seqBitLength` 不能超过 22
342
- - 序列号 0-4 保留用于时钟回拨处理
343
- - JavaScript 安全整数范围:`-(2^53-1)` 到 `2^53-1`
238
+ ## Performance
239
+
240
+ Throughput is determined by the number of available sequence slots per millisecond. Increasing `seqBitLength` scales linearly:
241
+
242
+ | seqBitLength | Slots/ms | Throughput |
243
+ | :-------------: | -------: | ------------------: |
244
+ | 3 | 3 | ~3,000 IDs/sec |
245
+ | 4 | 11 | ~11,000 IDs/sec |
246
+ | **6** (default) | **59** | **~58,000 IDs/sec** |
247
+ | 8 | 251 | ~247,000 IDs/sec |
248
+ | 10 | 1,019 | ~1,000,000 IDs/sec |
249
+ | 14 | 16,379 | ~4,500,000 IDs/sec |
250
+
251
+ > Measured on Node.js v22 (x64). Actual results vary by environment.
252
+ > Run `pnpm run benchmark` to probe your own machine.
253
+
254
+ | Metric | Value (default config) |
255
+ | ------------------------- | ---------------------: |
256
+ | Max worker nodes | 64 |
257
+ | Timestamp lifespan | ~139 years |
258
+ | P99 latency (single call) | < 1µs |
259
+
260
+ ## Benchmark
261
+
262
+ A built-in probe script measures the actual capability of the current environment:
263
+
264
+ ```bash
265
+ pnpm run benchmark
266
+ ```
267
+
268
+ It reports:
269
+
270
+ 1. **Single-call throughput** — peak `nextId()` IDs/sec
271
+ 2. **Batch throughput** — `nextBatch()` across different batch sizes
272
+ 3. **Latency percentiles** — P50 / P95 / P99 / P99.9 / Max
273
+ 4. **Algorithm comparison** — DRIFT vs TRADITIONAL side-by-side
274
+ 5. **Throughput by seqBitLength** — how bit allocation affects throughput
275
+ 6. **Memory footprint** — heap delta after 1M generations
276
+ 7. **Recommended thresholds** — suggested safe values for test assertions (60% of peak)
277
+
278
+ <details>
279
+ <summary>Example output</summary>
280
+
281
+ ```bash
282
+ station :: /app/projects/genid ‹main*› » pnpm run benchmark
283
+
284
+ > @cdlab996/genid@1.4.0 benchmark /app/projects/genid
285
+ > npx tsx scripts/benchmark.ts
286
+
287
+ ============================================================
288
+ GenidOptimized — Environment Capability Probe
289
+ Node v22.22.0 | linux x64
290
+ Date: 2026-04-01T08:41:07.669Z
291
+ ============================================================
292
+
293
+ ────────────────────────────────────────────────────────────
294
+ 1. Single-call throughput (nextId)
295
+ ────────────────────────────────────────────────────────────
296
+ Duration: 3001ms
297
+ Generated: 226,073
298
+ Throughput: 75,332 IDs/sec
299
+
300
+ ────────────────────────────────────────────────────────────
301
+ 2. Batch throughput (nextBatch)
302
+ ────────────────────────────────────────────────────────────
303
+ batch= 100 × 5000 => 61,665 IDs/sec
304
+ batch= 1,000 × 500 => 61,577 IDs/sec
305
+ batch= 10,000 × 50 => 61,716 IDs/sec
306
+ batch=100,000 × 5 => 61,644 IDs/sec
307
+
308
+ ────────────────────────────────────────────────────────────
309
+ 3. Single-call latency percentiles
310
+ ────────────────────────────────────────────────────────────
311
+ Samples: 100,000
312
+ Avg: 0µs
313
+ P50: 0µs
314
+ P95: 1µs
315
+ P99: 1µs
316
+ P99.9: 1µs
317
+ Max: 364µs
318
+
319
+ ────────────────────────────────────────────────────────────
320
+ 4. Algorithm comparison (DRIFT vs TRADITIONAL)
321
+ ────────────────────────────────────────────────────────────
322
+ DRIFT 58,296 IDs/sec drift=1
323
+ TRADITIONAL 59,000 IDs/sec drift=0
324
+
325
+ ────────────────────────────────────────────────────────────
326
+ 5. Throughput by sequence bit length
327
+ ────────────────────────────────────────────────────────────
328
+ seqBits= 3 maxSeq= 7 => 2,986 IDs/sec drift=1
329
+ seqBits= 4 maxSeq= 15 => 10,884 IDs/sec drift=1
330
+ seqBits= 6 maxSeq= 63 => 58,240 IDs/sec drift=1
331
+ seqBits= 8 maxSeq= 255 => 247,804 IDs/sec drift=1
332
+ seqBits=10 maxSeq= 1023 => 1,008,930 IDs/sec drift=1
333
+ seqBits=14 maxSeq=16383 => 4,130,701 IDs/sec drift=0
334
+
335
+ ────────────────────────────────────────────────────────────
336
+ 6. Memory footprint
337
+ ────────────────────────────────────────────────────────────
338
+ Generated: 1,000,000 IDs (not stored)
339
+ Heap delta: -6.27 MB
340
+ Note: Run with --expose-gc for accurate GC-forced measurement
341
+
342
+ ────────────────────────────────────────────────────────────
343
+ Summary — Recommended test thresholds
344
+ ────────────────────────────────────────────────────────────
345
+ Peak single-call: 75,332 IDs/sec
346
+ Peak batch: 61,716 IDs/sec
347
+ Suggested min threshold: 45,199 IDs/sec (60% of peak)
348
+ Suggested batch threshold: 37,029 IDs/sec (60% of peak)
349
+ Suggested P99 cap: 2µs (3× measured P99)
350
+ ```
351
+
352
+ </details>
353
+
354
+ ## Development
355
+
356
+ ```bash
357
+ pnpm install # Install dependencies
358
+ pnpm run build # Build (ESM + CJS)
359
+ pnpm run dev # Watch mode
360
+ pnpm run test # Run tests
361
+ pnpm run benchmark # Run environment capability probe
362
+ pnpm run typecheck # Type check
363
+ pnpm run lint # Lint (Biome)
364
+ pnpm run format # Format (Biome)
365
+ ```
344
366
 
345
- ## 性能指标
367
+ ## Notes
346
368
 
347
- - 单实例吞吐量:> 50,000 ID/秒
348
- - 默认配置下每毫秒可生成:59 个唯一 ID
349
- - 支持的最大节点数:2^workerIdBitLength(默认 64 个)
350
- - 时间戳可用时长:约 139 年(52 bits,从 baseTime 起算)
369
+ - Each worker/process must use a **unique workerId**
370
+ - Instances are **not thread-safe** — do not share across threads
371
+ - `workerIdBitLength + seqBitLength` must not exceed 22
372
+ - Sequence values 0-4 are reserved for clock-rollback handling
373
+ - When IDs exceed the JavaScript safe integer range (2^53-1), use `nextBigId()` or `nextId()` (auto-returns BigInt)
351
374
 
352
- ## 📜 License
375
+ ## License
353
376
 
354
377
  [MIT](./LICENSE) License © 2025-PRESENT [wudi](https://github.com/WuChenDi)