sol-trade-sdk 0.1.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 +390 -0
- package/dist/chunk-MMQAMIKR.mjs +3735 -0
- package/dist/chunk-NEZDFAYA.mjs +7744 -0
- package/dist/clients-VITWK7B6.mjs +1370 -0
- package/dist/index-1BK_FXsW.d.mts +2327 -0
- package/dist/index-1BK_FXsW.d.ts +2327 -0
- package/dist/index.d.mts +2659 -0
- package/dist/index.d.ts +2659 -0
- package/dist/index.js +13265 -0
- package/dist/index.mjs +562 -0
- package/dist/perf/index.d.mts +2 -0
- package/dist/perf/index.d.ts +2 -0
- package/dist/perf/index.js +3742 -0
- package/dist/perf/index.mjs +214 -0
- package/package.json +101 -0
- package/src/__tests__/complete_sdk.test.ts +354 -0
- package/src/__tests__/hotpath.test.ts +486 -0
- package/src/__tests__/nonce.test.ts +45 -0
- package/src/__tests__/sdk.test.ts +425 -0
- package/src/address-lookup/index.ts +197 -0
- package/src/cache/cache.ts +308 -0
- package/src/calc/index.ts +1058 -0
- package/src/calc/pumpfun.ts +124 -0
- package/src/common/bonding_curve.ts +272 -0
- package/src/common/compute-budget.ts +148 -0
- package/src/common/confirm-any-signature.ts +184 -0
- package/src/common/fast-timing.ts +481 -0
- package/src/common/fast_fn.ts +150 -0
- package/src/common/gas-fee-strategy.ts +253 -0
- package/src/common/map-pool.ts +23 -0
- package/src/common/nonce.ts +40 -0
- package/src/common/sdk-log.ts +460 -0
- package/src/common/seed.ts +381 -0
- package/src/common/spl-token.ts +578 -0
- package/src/common/subscription-handle.ts +644 -0
- package/src/common/trading-utils.ts +239 -0
- package/src/common/wsol-manager.ts +325 -0
- package/src/compute/compute_budget_manager.ts +187 -0
- package/src/compute/index.ts +21 -0
- package/src/constants/index.ts +96 -0
- package/src/execution/execution.ts +532 -0
- package/src/execution/index.ts +42 -0
- package/src/hotpath/executor.ts +464 -0
- package/src/hotpath/index.ts +64 -0
- package/src/hotpath/state.ts +435 -0
- package/src/index.ts +2117 -0
- package/src/instruction/bonk_builder.ts +730 -0
- package/src/instruction/index.ts +24 -0
- package/src/instruction/meteora_damm_v2_builder.ts +509 -0
- package/src/instruction/pumpfun_builder.ts +1183 -0
- package/src/instruction/pumpswap.ts +1123 -0
- package/src/instruction/raydium_amm_v4_builder.ts +692 -0
- package/src/instruction/raydium_cpmm_builder.ts +795 -0
- package/src/middleware/traits.ts +407 -0
- package/src/params/index.ts +483 -0
- package/src/perf/compiler-optimization.ts +529 -0
- package/src/perf/hardware.ts +631 -0
- package/src/perf/index.ts +9 -0
- package/src/perf/kernel-bypass.ts +656 -0
- package/src/perf/protocol.ts +682 -0
- package/src/perf/realtime.ts +592 -0
- package/src/perf/simd.ts +668 -0
- package/src/perf/syscall-bypass.ts +331 -0
- package/src/perf/ultra-low-latency.ts +505 -0
- package/src/perf/zero-copy.ts +589 -0
- package/src/pool/pool.ts +294 -0
- package/src/rpc/client.ts +345 -0
- package/src/sdk-errors.ts +13 -0
- package/src/security/index.ts +26 -0
- package/src/security/secure-key.ts +303 -0
- package/src/security/validators.ts +281 -0
- package/src/seed/pda.ts +262 -0
- package/src/serialization/index.ts +28 -0
- package/src/serialization/serialization.ts +288 -0
- package/src/swqos/clients.ts +1754 -0
- package/src/swqos/index.ts +50 -0
- package/src/swqos/providers.ts +1707 -0
- package/src/trading/core/async-executor.ts +702 -0
- package/src/trading/core/confirmation-monitor.ts +711 -0
- package/src/trading/core/index.ts +82 -0
- package/src/trading/core/retry-handler.ts +683 -0
- package/src/trading/core/transaction-pool.ts +780 -0
- package/src/trading/executor.ts +385 -0
- package/src/trading/factory.ts +282 -0
- package/src/trading/index.ts +30 -0
- package/src/types.ts +8 -0
- package/src/utils/index.ts +155 -0
|
@@ -0,0 +1,505 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ultra-Low Latency (ULL) Module for Sol Trade SDK
|
|
3
|
+
* Provides memory pools, lock-free queues, and latency optimization.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// ===== Types =====
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Configuration for ultra-low latency optimizations
|
|
10
|
+
*/
|
|
11
|
+
export interface UltraLowLatencyConfig {
|
|
12
|
+
/** Memory pool size per object type */
|
|
13
|
+
memoryPoolSize: number;
|
|
14
|
+
/** Lock-free queue capacity */
|
|
15
|
+
queueCapacity: number;
|
|
16
|
+
/** Enable busy spinning instead of yielding */
|
|
17
|
+
enableBusySpin: boolean;
|
|
18
|
+
/** Spin count before yielding */
|
|
19
|
+
spinCount: number;
|
|
20
|
+
/** Enable memory prefetching */
|
|
21
|
+
enablePrefetch: boolean;
|
|
22
|
+
/** NUMA-aware memory allocation */
|
|
23
|
+
numaAware: boolean;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Default ULL configuration
|
|
28
|
+
*/
|
|
29
|
+
export function defaultUltraLowLatencyConfig(): UltraLowLatencyConfig {
|
|
30
|
+
return {
|
|
31
|
+
memoryPoolSize: 1024,
|
|
32
|
+
queueCapacity: 4096,
|
|
33
|
+
enableBusySpin: true,
|
|
34
|
+
spinCount: 1000,
|
|
35
|
+
enablePrefetch: true,
|
|
36
|
+
numaAware: false,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Latency statistics
|
|
42
|
+
*/
|
|
43
|
+
export interface LatencyStats {
|
|
44
|
+
minLatencyUs: number;
|
|
45
|
+
maxLatencyUs: number;
|
|
46
|
+
avgLatencyUs: number;
|
|
47
|
+
p50LatencyUs: number;
|
|
48
|
+
p99LatencyUs: number;
|
|
49
|
+
p999LatencyUs: number;
|
|
50
|
+
totalOperations: number;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// ===== Memory Pool =====
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* High-performance memory pool for object reuse.
|
|
57
|
+
* Reduces GC pressure and allocation latency.
|
|
58
|
+
*/
|
|
59
|
+
export class MemoryPool<T> {
|
|
60
|
+
private pool: T[] = [];
|
|
61
|
+
private factory: () => T;
|
|
62
|
+
private resetFn: (obj: T) => void;
|
|
63
|
+
private maxSize: number;
|
|
64
|
+
private leased = 0;
|
|
65
|
+
|
|
66
|
+
constructor(
|
|
67
|
+
factory: () => T,
|
|
68
|
+
resetFn: (obj: T) => void,
|
|
69
|
+
maxSize: number = 1024
|
|
70
|
+
) {
|
|
71
|
+
this.factory = factory;
|
|
72
|
+
this.resetFn = resetFn;
|
|
73
|
+
this.maxSize = maxSize;
|
|
74
|
+
|
|
75
|
+
// Pre-allocate objects
|
|
76
|
+
for (let i = 0; i < maxSize; i++) {
|
|
77
|
+
this.pool.push(factory());
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Acquire an object from the pool
|
|
83
|
+
*/
|
|
84
|
+
acquire(): T {
|
|
85
|
+
this.leased++;
|
|
86
|
+
if (this.pool.length > 0) {
|
|
87
|
+
return this.pool.pop()!;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return this.factory();
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Release an object back to the pool
|
|
95
|
+
*/
|
|
96
|
+
release(obj: T): void {
|
|
97
|
+
if (this.leased <= 0) return;
|
|
98
|
+
this.leased--;
|
|
99
|
+
|
|
100
|
+
if (this.pool.length < this.maxSize) {
|
|
101
|
+
this.resetFn(obj);
|
|
102
|
+
this.pool.push(obj);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Execute a function with a pooled object
|
|
108
|
+
*/
|
|
109
|
+
with<R>(fn: (obj: T) => R): R {
|
|
110
|
+
const obj = this.acquire();
|
|
111
|
+
try {
|
|
112
|
+
return fn(obj);
|
|
113
|
+
} finally {
|
|
114
|
+
this.release(obj);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Get pool statistics
|
|
120
|
+
*/
|
|
121
|
+
getStats(): { available: number; inUse: number; total: number } {
|
|
122
|
+
return {
|
|
123
|
+
available: this.pool.length,
|
|
124
|
+
inUse: this.leased,
|
|
125
|
+
total: this.pool.length + this.leased,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// ===== Lock-Free Queue =====
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Lock-free circular buffer queue for single-producer single-consumer scenarios.
|
|
134
|
+
* Uses atomic operations for synchronization.
|
|
135
|
+
*/
|
|
136
|
+
export class LockFreeQueue<T> {
|
|
137
|
+
private buffer: (T | undefined)[];
|
|
138
|
+
private capacity: number;
|
|
139
|
+
private mask: number;
|
|
140
|
+
private head: number = 0; // Write position
|
|
141
|
+
private tail: number = 0; // Read position
|
|
142
|
+
private config: UltraLowLatencyConfig;
|
|
143
|
+
|
|
144
|
+
constructor(capacity: number = 4096, config?: UltraLowLatencyConfig) {
|
|
145
|
+
// Round up to power of 2
|
|
146
|
+
this.capacity = Math.pow(2, Math.ceil(Math.log2(capacity)));
|
|
147
|
+
this.mask = this.capacity - 1;
|
|
148
|
+
this.buffer = new Array(this.capacity).fill(undefined);
|
|
149
|
+
this.config = config || defaultUltraLowLatencyConfig();
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Enqueue an item (producer only)
|
|
154
|
+
*/
|
|
155
|
+
enqueue(item: T): boolean {
|
|
156
|
+
const nextHead = (this.head + 1) & this.mask;
|
|
157
|
+
|
|
158
|
+
// Check if full
|
|
159
|
+
if (nextHead === this.tail) {
|
|
160
|
+
return false; // Queue full
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
this.buffer[this.head] = item;
|
|
164
|
+
this.head = nextHead;
|
|
165
|
+
|
|
166
|
+
return true;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Dequeue an item (consumer only)
|
|
171
|
+
*/
|
|
172
|
+
dequeue(): T | undefined {
|
|
173
|
+
if (this.tail === this.head) {
|
|
174
|
+
return undefined; // Queue empty
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
const item = this.buffer[this.tail];
|
|
178
|
+
this.buffer[this.tail] = undefined;
|
|
179
|
+
this.tail = (this.tail + 1) & this.mask;
|
|
180
|
+
|
|
181
|
+
return item;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Try dequeue with spinning
|
|
186
|
+
*/
|
|
187
|
+
dequeueSpin(timeoutUs: number = 1000): T | undefined {
|
|
188
|
+
const startTime = performance.now();
|
|
189
|
+
const timeoutMs = timeoutUs / 1000;
|
|
190
|
+
|
|
191
|
+
let spins = 0;
|
|
192
|
+
while (performance.now() - startTime < timeoutMs) {
|
|
193
|
+
const item = this.dequeue();
|
|
194
|
+
if (item !== undefined) {
|
|
195
|
+
return item;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
if (this.config.enableBusySpin && spins < this.config.spinCount) {
|
|
199
|
+
spins++;
|
|
200
|
+
// Busy spin
|
|
201
|
+
continue;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// Yield
|
|
205
|
+
spins = 0;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
return undefined;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Get current size
|
|
213
|
+
*/
|
|
214
|
+
size(): number {
|
|
215
|
+
return (this.head - this.tail) & this.mask;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Check if empty
|
|
220
|
+
*/
|
|
221
|
+
isEmpty(): boolean {
|
|
222
|
+
return this.head === this.tail;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Check if full
|
|
227
|
+
*/
|
|
228
|
+
isFull(): boolean {
|
|
229
|
+
return ((this.head + 1) & this.mask) === this.tail;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Clear the queue
|
|
234
|
+
*/
|
|
235
|
+
clear(): void {
|
|
236
|
+
this.head = 0;
|
|
237
|
+
this.tail = 0;
|
|
238
|
+
this.buffer.fill(undefined);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// ===== Multi-Producer Multi-Consumer Queue =====
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Thread-safe queue supporting multiple producers and consumers.
|
|
246
|
+
* Uses compare-and-swap for atomic operations.
|
|
247
|
+
*/
|
|
248
|
+
export class MPMCQueue<T> {
|
|
249
|
+
private buffer: Array<{ item: T | undefined; sequence: number }>;
|
|
250
|
+
private capacity: number;
|
|
251
|
+
private mask: number;
|
|
252
|
+
private enqueuePos: number = 0;
|
|
253
|
+
private dequeuePos: number = 0;
|
|
254
|
+
|
|
255
|
+
constructor(capacity: number = 4096) {
|
|
256
|
+
this.capacity = Math.pow(2, Math.ceil(Math.log2(capacity)));
|
|
257
|
+
this.mask = this.capacity - 1;
|
|
258
|
+
this.buffer = new Array(this.capacity);
|
|
259
|
+
|
|
260
|
+
for (let i = 0; i < this.capacity; i++) {
|
|
261
|
+
this.buffer[i] = { item: undefined, sequence: i };
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Enqueue an item (thread-safe)
|
|
267
|
+
*/
|
|
268
|
+
enqueue(item: T): boolean {
|
|
269
|
+
let pos = this.enqueuePos;
|
|
270
|
+
|
|
271
|
+
while (true) {
|
|
272
|
+
const slot = this.buffer[pos & this.mask]!;
|
|
273
|
+
const seq = slot.sequence;
|
|
274
|
+
const diff = seq - pos;
|
|
275
|
+
|
|
276
|
+
if (diff === 0) {
|
|
277
|
+
// Try to claim slot
|
|
278
|
+
if (this.compareAndSwapEnqueuePos(pos, pos + 1)) {
|
|
279
|
+
slot.item = item;
|
|
280
|
+
slot.sequence = pos + 1;
|
|
281
|
+
return true;
|
|
282
|
+
}
|
|
283
|
+
// Failed, retry
|
|
284
|
+
pos = this.enqueuePos;
|
|
285
|
+
} else if (diff < 0) {
|
|
286
|
+
// Queue full
|
|
287
|
+
return false;
|
|
288
|
+
} else {
|
|
289
|
+
// Another thread moved forward, retry
|
|
290
|
+
pos = this.enqueuePos;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* Dequeue an item (thread-safe)
|
|
297
|
+
*/
|
|
298
|
+
dequeue(): T | undefined {
|
|
299
|
+
let pos = this.dequeuePos;
|
|
300
|
+
|
|
301
|
+
while (true) {
|
|
302
|
+
const slot = this.buffer[pos & this.mask]!;
|
|
303
|
+
const seq = slot.sequence;
|
|
304
|
+
const diff = seq - (pos + 1);
|
|
305
|
+
|
|
306
|
+
if (diff === 0) {
|
|
307
|
+
// Try to claim slot
|
|
308
|
+
if (this.compareAndSwapDequeuePos(pos, pos + 1)) {
|
|
309
|
+
const item = slot.item;
|
|
310
|
+
slot.item = undefined;
|
|
311
|
+
slot.sequence = pos + this.mask + 1;
|
|
312
|
+
return item;
|
|
313
|
+
}
|
|
314
|
+
// Failed, retry
|
|
315
|
+
pos = this.dequeuePos;
|
|
316
|
+
} else if (diff < 0) {
|
|
317
|
+
// Queue empty
|
|
318
|
+
return undefined;
|
|
319
|
+
} else {
|
|
320
|
+
// Another thread moved forward, retry
|
|
321
|
+
pos = this.dequeuePos;
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
private compareAndSwapEnqueuePos(expected: number, value: number): boolean {
|
|
327
|
+
if (this.enqueuePos === expected) {
|
|
328
|
+
this.enqueuePos = value;
|
|
329
|
+
return true;
|
|
330
|
+
}
|
|
331
|
+
return false;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
private compareAndSwapDequeuePos(expected: number, value: number): boolean {
|
|
335
|
+
if (this.dequeuePos === expected) {
|
|
336
|
+
this.dequeuePos = value;
|
|
337
|
+
return true;
|
|
338
|
+
}
|
|
339
|
+
return false;
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
// ===== Latency Optimizer =====
|
|
344
|
+
|
|
345
|
+
/**
|
|
346
|
+
* Latency optimizer for trading operations.
|
|
347
|
+
* Provides latency measurement, optimization, and reporting.
|
|
348
|
+
*/
|
|
349
|
+
export class LatencyOptimizer {
|
|
350
|
+
private latencies: number[] = [];
|
|
351
|
+
private maxSamples: number;
|
|
352
|
+
private config: UltraLowLatencyConfig;
|
|
353
|
+
private optimizationCallbacks: Array<() => void> = [];
|
|
354
|
+
|
|
355
|
+
constructor(maxSamples: number = 10000, config?: UltraLowLatencyConfig) {
|
|
356
|
+
this.maxSamples = maxSamples;
|
|
357
|
+
this.config = config || defaultUltraLowLatencyConfig();
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
/**
|
|
361
|
+
* Record a latency measurement
|
|
362
|
+
*/
|
|
363
|
+
recordLatency(latencyUs: number): void {
|
|
364
|
+
this.latencies.push(latencyUs);
|
|
365
|
+
|
|
366
|
+
if (this.latencies.length > this.maxSamples) {
|
|
367
|
+
this.latencies.shift();
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
/**
|
|
372
|
+
* Measure and record function execution time
|
|
373
|
+
*/
|
|
374
|
+
measure<T>(fn: () => T): { result: T; latencyUs: number } {
|
|
375
|
+
const start = performance.now();
|
|
376
|
+
const result = fn();
|
|
377
|
+
const latencyUs = (performance.now() - start) * 1000;
|
|
378
|
+
this.recordLatency(latencyUs);
|
|
379
|
+
return { result, latencyUs };
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
/**
|
|
383
|
+
* Get latency statistics
|
|
384
|
+
*/
|
|
385
|
+
getStats(): LatencyStats {
|
|
386
|
+
if (this.latencies.length === 0) {
|
|
387
|
+
return {
|
|
388
|
+
minLatencyUs: 0,
|
|
389
|
+
maxLatencyUs: 0,
|
|
390
|
+
avgLatencyUs: 0,
|
|
391
|
+
p50LatencyUs: 0,
|
|
392
|
+
p99LatencyUs: 0,
|
|
393
|
+
p999LatencyUs: 0,
|
|
394
|
+
totalOperations: 0,
|
|
395
|
+
};
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
const sorted = [...this.latencies].sort((a, b) => a - b);
|
|
399
|
+
const n = sorted.length;
|
|
400
|
+
|
|
401
|
+
return {
|
|
402
|
+
minLatencyUs: sorted[0] ?? 0,
|
|
403
|
+
maxLatencyUs: sorted[n - 1] ?? 0,
|
|
404
|
+
avgLatencyUs: sorted.reduce((a, b) => a + b, 0) / n,
|
|
405
|
+
p50LatencyUs: sorted[Math.floor(n * 0.5)] ?? 0,
|
|
406
|
+
p99LatencyUs: sorted[Math.floor(n * 0.99)] ?? 0,
|
|
407
|
+
p999LatencyUs: sorted[Math.floor(n * 0.999)] ?? 0,
|
|
408
|
+
totalOperations: n,
|
|
409
|
+
};
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
/**
|
|
413
|
+
* Register an optimization callback
|
|
414
|
+
*/
|
|
415
|
+
onOptimization(callback: () => void): void {
|
|
416
|
+
this.optimizationCallbacks.push(callback);
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
/**
|
|
420
|
+
* Trigger optimization
|
|
421
|
+
*/
|
|
422
|
+
optimize(): void {
|
|
423
|
+
for (const callback of this.optimizationCallbacks) {
|
|
424
|
+
try {
|
|
425
|
+
callback();
|
|
426
|
+
} catch (error) {
|
|
427
|
+
console.error('Optimization callback error:', error);
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
/**
|
|
433
|
+
* Reset statistics
|
|
434
|
+
*/
|
|
435
|
+
reset(): void {
|
|
436
|
+
this.latencies = [];
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
// ===== Prefetch Utilities =====
|
|
441
|
+
|
|
442
|
+
/**
|
|
443
|
+
* Software prefetch hint (no-op in JS, but documents intent)
|
|
444
|
+
*/
|
|
445
|
+
export function prefetch<T>(obj: T): void {
|
|
446
|
+
// In JavaScript, we can't actually prefetch memory
|
|
447
|
+
// This function serves as documentation and potential WASM integration point
|
|
448
|
+
// Access the object to potentially load it into cache
|
|
449
|
+
if (obj && typeof obj === 'object') {
|
|
450
|
+
// Touch first property to potentially trigger cache load
|
|
451
|
+
const key = Object.keys(obj)[0];
|
|
452
|
+
const _ = key === undefined ? undefined : (obj as any)[key];
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
/**
|
|
457
|
+
* Prefetch an array element
|
|
458
|
+
*/
|
|
459
|
+
export function prefetchArray<T>(arr: T[], index: number): void {
|
|
460
|
+
const _ = arr[index];
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
// ===== Convenience Functions =====
|
|
464
|
+
|
|
465
|
+
/**
|
|
466
|
+
* Create a memory pool with default configuration
|
|
467
|
+
*/
|
|
468
|
+
export function createMemoryPool<T>(
|
|
469
|
+
factory: () => T,
|
|
470
|
+
resetFn: (obj: T) => void,
|
|
471
|
+
size?: number
|
|
472
|
+
): MemoryPool<T> {
|
|
473
|
+
return new MemoryPool(factory, resetFn, size || defaultUltraLowLatencyConfig().memoryPoolSize);
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
/**
|
|
477
|
+
* Create a lock-free queue
|
|
478
|
+
*/
|
|
479
|
+
export function createLockFreeQueue<T>(capacity?: number): LockFreeQueue<T> {
|
|
480
|
+
return new LockFreeQueue(capacity);
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
/**
|
|
484
|
+
* Create an MPMC queue
|
|
485
|
+
*/
|
|
486
|
+
export function createMPMCQueue<T>(capacity?: number): MPMCQueue<T> {
|
|
487
|
+
return new MPMCQueue(capacity);
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
/**
|
|
491
|
+
* Busy spin for a number of iterations
|
|
492
|
+
*/
|
|
493
|
+
export function busySpin(iterations: number): void {
|
|
494
|
+
for (let i = 0; i < iterations; i++) {
|
|
495
|
+
// Prevent optimization
|
|
496
|
+
Math.random();
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
/**
|
|
501
|
+
* Yield to event loop
|
|
502
|
+
*/
|
|
503
|
+
export function yieldToEventLoop(): Promise<void> {
|
|
504
|
+
return new Promise(resolve => setImmediate(resolve));
|
|
505
|
+
}
|