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,3735 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
3
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
4
|
+
}) : x)(function(x) {
|
|
5
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
6
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
7
|
+
});
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
// src/perf/index.ts
|
|
14
|
+
var perf_exports = {};
|
|
15
|
+
__export(perf_exports, {
|
|
16
|
+
AlignedBuffer: () => AlignedBuffer,
|
|
17
|
+
AsyncSocket: () => AsyncSocket,
|
|
18
|
+
BranchOptimizer: () => BranchOptimizer,
|
|
19
|
+
BufferPool: () => BufferPool,
|
|
20
|
+
CACHE_LINE_SIZE: () => CACHE_LINE_SIZE,
|
|
21
|
+
CPUAffinity: () => CPUAffinity,
|
|
22
|
+
CacheOptimizer: () => CacheOptimizer,
|
|
23
|
+
ComputeBudgetOptimizer: () => ComputeBudgetOptimizer,
|
|
24
|
+
CryptoSIMD: () => CryptoSIMD,
|
|
25
|
+
DirectIOFile: () => DirectIOFile,
|
|
26
|
+
FastTimeProvider: () => FastTimeProvider,
|
|
27
|
+
FixedBufferView: () => FixedBufferView,
|
|
28
|
+
Float32x4: () => Float32x4,
|
|
29
|
+
FuncCache: () => FuncCache,
|
|
30
|
+
HardwareMonitor: () => HardwareMonitor,
|
|
31
|
+
IOBatchProcessor: () => IOBatchProcessor,
|
|
32
|
+
IOOperation: () => IOOperation,
|
|
33
|
+
InstructionBatcher: () => InstructionBatcher,
|
|
34
|
+
KernelBypassManager: () => KernelBypassManager,
|
|
35
|
+
LatencyMonitor: () => LatencyMonitor,
|
|
36
|
+
LatencyOptimizer: () => LatencyOptimizer,
|
|
37
|
+
LockFreeQueue: () => LockFreeQueue,
|
|
38
|
+
LoopOptimizer: () => LoopOptimizer,
|
|
39
|
+
MPMCQueue: () => MPMCQueue,
|
|
40
|
+
MemoryMappedFile: () => MemoryMappedFile,
|
|
41
|
+
MemoryOps: () => MemoryOps,
|
|
42
|
+
MemoryPool: () => MemoryPool,
|
|
43
|
+
NUMAOptimizer: () => NUMAOptimizer,
|
|
44
|
+
OptimizedMath: () => OptimizedMath,
|
|
45
|
+
PerformanceGovernor: () => PerformanceGovernor,
|
|
46
|
+
ProfileGuidedOptimizer: () => ProfileGuidedOptimizer,
|
|
47
|
+
RealtimeTuner: () => RealtimeTuner,
|
|
48
|
+
SIMDDetector: () => SIMDDetector,
|
|
49
|
+
SchedulerPolicy: () => SchedulerPolicy,
|
|
50
|
+
SpinLock: () => SpinLock,
|
|
51
|
+
SyscallBypassManager: () => SyscallBypassManager,
|
|
52
|
+
ThreadPriority: () => ThreadPriority,
|
|
53
|
+
ThreadPriorityLevel: () => ThreadPriorityLevel,
|
|
54
|
+
TransactionBuilder: () => TransactionBuilder,
|
|
55
|
+
TransactionOptimizer: () => TransactionOptimizer,
|
|
56
|
+
VectorizedMath: () => VectorizedMath,
|
|
57
|
+
ZeroCopyBuffer: () => ZeroCopyBuffer,
|
|
58
|
+
ZeroCopySerializer: () => ZeroCopySerializer,
|
|
59
|
+
busySpin: () => busySpin,
|
|
60
|
+
busyWait: () => busyWait,
|
|
61
|
+
calculateOptimalPrice: () => calculateOptimalPrice,
|
|
62
|
+
coldPath: () => coldPath,
|
|
63
|
+
copyBytes: () => copyBytes,
|
|
64
|
+
createBufferPool: () => createBufferPool,
|
|
65
|
+
createCPUAffinity: () => createCPUAffinity,
|
|
66
|
+
createCacheOptimizer: () => createCacheOptimizer,
|
|
67
|
+
createComputeBudgetOptimizer: () => createComputeBudgetOptimizer,
|
|
68
|
+
createCryptoSIMD: () => createCryptoSIMD,
|
|
69
|
+
createHardwareMonitor: () => createHardwareMonitor,
|
|
70
|
+
createInstructionBatcher: () => createInstructionBatcher,
|
|
71
|
+
createLatencyMonitor: () => createLatencyMonitor,
|
|
72
|
+
createLockFreeQueue: () => createLockFreeQueue,
|
|
73
|
+
createMPMCQueue: () => createMPMCQueue,
|
|
74
|
+
createMemoryPool: () => createMemoryPool,
|
|
75
|
+
createNUMAOptimizer: () => createNUMAOptimizer,
|
|
76
|
+
createPerformanceGovernor: () => createPerformanceGovernor,
|
|
77
|
+
createRealtimeTuner: () => createRealtimeTuner,
|
|
78
|
+
createSIMDDetector: () => createSIMDDetector,
|
|
79
|
+
createSerializer: () => createSerializer,
|
|
80
|
+
createSyscallBypassManager: () => createSyscallBypassManager,
|
|
81
|
+
createThreadPriority: () => createThreadPriority,
|
|
82
|
+
createTimer: () => createTimer,
|
|
83
|
+
createTransactionBuilder: () => createTransactionBuilder,
|
|
84
|
+
createTransactionOptimizer: () => createTransactionOptimizer,
|
|
85
|
+
createVectorizedMath: () => createVectorizedMath,
|
|
86
|
+
createView: () => createView,
|
|
87
|
+
createZeroCopyBuffer: () => createZeroCopyBuffer,
|
|
88
|
+
defaultAffinityConfig: () => defaultAffinityConfig,
|
|
89
|
+
defaultBufferPoolConfig: () => defaultBufferPoolConfig,
|
|
90
|
+
defaultIOUringConfig: () => defaultIOUringConfig,
|
|
91
|
+
defaultJITConfig: () => defaultJITConfig,
|
|
92
|
+
defaultNUMAConfig: () => defaultNUMAConfig,
|
|
93
|
+
defaultRealtimeConfig: () => defaultRealtimeConfig,
|
|
94
|
+
defaultSIMDConfig: () => defaultSIMDConfig,
|
|
95
|
+
defaultSyscallBypassConfig: () => defaultSyscallBypassConfig,
|
|
96
|
+
defaultTransactionConfig: () => defaultTransactionConfig,
|
|
97
|
+
defaultUltraLowLatencyConfig: () => defaultUltraLowLatencyConfig,
|
|
98
|
+
detectCPUFeatures: () => detectCPUFeatures,
|
|
99
|
+
estimateCompute: () => estimateCompute,
|
|
100
|
+
fastInvSqrt: () => fastInvSqrt,
|
|
101
|
+
fastNowMs: () => fastNowMs,
|
|
102
|
+
fastNowNs: () => fastNowNs,
|
|
103
|
+
fastNowUs: () => fastNowUs,
|
|
104
|
+
getGlobalTimeProvider: () => getGlobalTimeProvider,
|
|
105
|
+
getKernelBypassManager: () => getKernelBypassManager,
|
|
106
|
+
getOptimalSIMDWidth: () => getOptimalSIMDWidth,
|
|
107
|
+
getProfileOptimizer: () => getProfileOptimizer,
|
|
108
|
+
getSystemCPUInfo: () => getSystemCPUInfo,
|
|
109
|
+
getSystemMemoryInfo: () => getSystemMemoryInfo,
|
|
110
|
+
hotPath: () => hotPath,
|
|
111
|
+
isSIMDAvailable: () => isSIMDAvailable,
|
|
112
|
+
likely: () => likely,
|
|
113
|
+
measureTime: () => measureTime,
|
|
114
|
+
prefetch: () => prefetch,
|
|
115
|
+
prefetchArray: () => prefetchArray,
|
|
116
|
+
prefetchHint: () => prefetchHint,
|
|
117
|
+
profile: () => profile,
|
|
118
|
+
spinLock: () => spinLock,
|
|
119
|
+
unlikely: () => unlikely,
|
|
120
|
+
yieldToEventLoop: () => yieldToEventLoop
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
// src/perf/compiler-optimization.ts
|
|
124
|
+
function defaultJITConfig() {
|
|
125
|
+
return {
|
|
126
|
+
enabled: true,
|
|
127
|
+
cacheSize: 128,
|
|
128
|
+
optimizationLevel: "O3",
|
|
129
|
+
inlineThreshold: 1e3,
|
|
130
|
+
loopVectorize: true,
|
|
131
|
+
slpVectorize: true
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
var BranchOptimizer = class {
|
|
135
|
+
/**
|
|
136
|
+
* Hint that the condition is likely true
|
|
137
|
+
* Use this to guide branch prediction in hot paths
|
|
138
|
+
*/
|
|
139
|
+
static likely(condition) {
|
|
140
|
+
return condition;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Hint that the condition is likely false
|
|
144
|
+
* Use this to guide branch prediction in error handling paths
|
|
145
|
+
*/
|
|
146
|
+
static unlikely(condition) {
|
|
147
|
+
return condition;
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
function likely(condition) {
|
|
151
|
+
return condition;
|
|
152
|
+
}
|
|
153
|
+
function unlikely(condition) {
|
|
154
|
+
return condition;
|
|
155
|
+
}
|
|
156
|
+
var LoopOptimizer = class {
|
|
157
|
+
/**
|
|
158
|
+
* Hint that a loop should be unrolled
|
|
159
|
+
*/
|
|
160
|
+
static unrollHint(factor) {
|
|
161
|
+
return factor;
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Hint that a loop should be vectorized
|
|
165
|
+
*/
|
|
166
|
+
static vectorizeHint() {
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Hint that a loop should be parallelized
|
|
170
|
+
*/
|
|
171
|
+
static parallelHint() {
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
var CACHE_LINE_SIZE = 64;
|
|
175
|
+
var AlignedBuffer = class {
|
|
176
|
+
data;
|
|
177
|
+
offset;
|
|
178
|
+
constructor(size, align = CACHE_LINE_SIZE) {
|
|
179
|
+
const padded = size + align;
|
|
180
|
+
this.data = Buffer.alloc(padded);
|
|
181
|
+
this.offset = 0;
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Get the aligned buffer
|
|
185
|
+
*/
|
|
186
|
+
get buffer() {
|
|
187
|
+
return this.data.slice(this.offset);
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Get the underlying buffer
|
|
191
|
+
*/
|
|
192
|
+
get underlying() {
|
|
193
|
+
return this.data;
|
|
194
|
+
}
|
|
195
|
+
};
|
|
196
|
+
function prefetchHint(address) {
|
|
197
|
+
}
|
|
198
|
+
var ProfileGuidedOptimizer = class {
|
|
199
|
+
profileData = /* @__PURE__ */ new Map();
|
|
200
|
+
callCounts = /* @__PURE__ */ new Map();
|
|
201
|
+
/**
|
|
202
|
+
* Instrument a function for profiling
|
|
203
|
+
*/
|
|
204
|
+
instrument(name, fn) {
|
|
205
|
+
const self = this;
|
|
206
|
+
return (function(...args) {
|
|
207
|
+
const count = (self.callCounts.get(name) || 0) + 1;
|
|
208
|
+
self.callCounts.set(name, count);
|
|
209
|
+
const start = performance.now();
|
|
210
|
+
const result = fn.apply(this, args);
|
|
211
|
+
const elapsed = performance.now() - start;
|
|
212
|
+
let profile2 = self.profileData.get(name);
|
|
213
|
+
if (!profile2) {
|
|
214
|
+
profile2 = {
|
|
215
|
+
calls: 0,
|
|
216
|
+
totalTime: 0,
|
|
217
|
+
minTime: Infinity,
|
|
218
|
+
maxTime: 0
|
|
219
|
+
};
|
|
220
|
+
self.profileData.set(name, profile2);
|
|
221
|
+
}
|
|
222
|
+
profile2.calls = count;
|
|
223
|
+
profile2.totalTime += elapsed;
|
|
224
|
+
if (elapsed < profile2.minTime) {
|
|
225
|
+
profile2.minTime = elapsed;
|
|
226
|
+
}
|
|
227
|
+
if (elapsed > profile2.maxTime) {
|
|
228
|
+
profile2.maxTime = elapsed;
|
|
229
|
+
}
|
|
230
|
+
return result;
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Get the most frequently called functions
|
|
235
|
+
*/
|
|
236
|
+
getHotFunctions(topN = 10) {
|
|
237
|
+
const results = [];
|
|
238
|
+
this.callCounts.forEach((count, name) => {
|
|
239
|
+
results.push({ name, count });
|
|
240
|
+
});
|
|
241
|
+
results.sort((a, b) => b.count - a.count);
|
|
242
|
+
return results.slice(0, topN);
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Get functions with highest average execution time
|
|
246
|
+
*/
|
|
247
|
+
getSlowFunctions(topN = 10) {
|
|
248
|
+
const results = [];
|
|
249
|
+
this.profileData.forEach((profile2, name) => {
|
|
250
|
+
if (profile2.calls > 0) {
|
|
251
|
+
results.push({
|
|
252
|
+
name,
|
|
253
|
+
avgTime: profile2.totalTime / profile2.calls
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
});
|
|
257
|
+
results.sort((a, b) => b.avgTime - a.avgTime);
|
|
258
|
+
return results.slice(0, topN);
|
|
259
|
+
}
|
|
260
|
+
};
|
|
261
|
+
var OptimizedMath = class {
|
|
262
|
+
/**
|
|
263
|
+
* Fast exponential approximation
|
|
264
|
+
*/
|
|
265
|
+
static fastExp(x) {
|
|
266
|
+
if (x < -708) return 0;
|
|
267
|
+
if (x > 709) return Infinity;
|
|
268
|
+
return Math.exp(x);
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* Fast logarithm
|
|
272
|
+
*/
|
|
273
|
+
static fastLog(x) {
|
|
274
|
+
return Math.log(x);
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Fast square root
|
|
278
|
+
*/
|
|
279
|
+
static fastSqrt(x) {
|
|
280
|
+
return Math.sqrt(x);
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Fast inverse square root (Quake III algorithm)
|
|
284
|
+
*/
|
|
285
|
+
static fastInvSqrt(x) {
|
|
286
|
+
if (x <= 0) return Infinity;
|
|
287
|
+
const threehalfs = 1.5;
|
|
288
|
+
const x2 = x * 0.5;
|
|
289
|
+
let y = x;
|
|
290
|
+
const buf = new ArrayBuffer(4);
|
|
291
|
+
const f32 = new Float32Array(buf);
|
|
292
|
+
const u32 = new Uint32Array(buf);
|
|
293
|
+
f32[0] = y;
|
|
294
|
+
u32[0] = 1597463007 - (u32[0] >> 1);
|
|
295
|
+
y = f32[0];
|
|
296
|
+
y = y * (threehalfs - x2 * y * y);
|
|
297
|
+
return y;
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* Fast power
|
|
301
|
+
*/
|
|
302
|
+
static fastPow(base, exp) {
|
|
303
|
+
return Math.pow(base, exp);
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* Fast absolute value for integers
|
|
307
|
+
*/
|
|
308
|
+
static fastAbs(x) {
|
|
309
|
+
return x < 0 ? -x : x;
|
|
310
|
+
}
|
|
311
|
+
};
|
|
312
|
+
function fastInvSqrt(x) {
|
|
313
|
+
return OptimizedMath.fastInvSqrt(x);
|
|
314
|
+
}
|
|
315
|
+
var FuncCache = class {
|
|
316
|
+
cache = /* @__PURE__ */ new Map();
|
|
317
|
+
hits = 0;
|
|
318
|
+
misses = 0;
|
|
319
|
+
maxSize;
|
|
320
|
+
constructor(maxSize = 128) {
|
|
321
|
+
this.maxSize = maxSize;
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* Get a cached value
|
|
325
|
+
*/
|
|
326
|
+
get(key) {
|
|
327
|
+
const value = this.cache.get(key);
|
|
328
|
+
if (value !== void 0) {
|
|
329
|
+
this.hits++;
|
|
330
|
+
return value;
|
|
331
|
+
}
|
|
332
|
+
this.misses++;
|
|
333
|
+
return void 0;
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* Set a cached value
|
|
337
|
+
*/
|
|
338
|
+
set(key, value) {
|
|
339
|
+
if (this.cache.size >= this.maxSize) {
|
|
340
|
+
const firstKey = this.cache.keys().next().value;
|
|
341
|
+
if (firstKey !== void 0) {
|
|
342
|
+
this.cache.delete(firstKey);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
this.cache.set(key, value);
|
|
346
|
+
}
|
|
347
|
+
/**
|
|
348
|
+
* Get cache statistics
|
|
349
|
+
*/
|
|
350
|
+
stats() {
|
|
351
|
+
const total = this.hits + this.misses;
|
|
352
|
+
return {
|
|
353
|
+
hits: this.hits,
|
|
354
|
+
misses: this.misses,
|
|
355
|
+
hitRate: total > 0 ? this.hits / total : 0
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* Clear the cache
|
|
360
|
+
*/
|
|
361
|
+
clear() {
|
|
362
|
+
this.cache.clear();
|
|
363
|
+
this.hits = 0;
|
|
364
|
+
this.misses = 0;
|
|
365
|
+
}
|
|
366
|
+
};
|
|
367
|
+
var SpinLock = class {
|
|
368
|
+
locked = false;
|
|
369
|
+
/**
|
|
370
|
+
* Acquire the lock
|
|
371
|
+
*/
|
|
372
|
+
async lock() {
|
|
373
|
+
while (this.locked) {
|
|
374
|
+
await new Promise((resolve) => setImmediate(resolve));
|
|
375
|
+
}
|
|
376
|
+
this.locked = true;
|
|
377
|
+
}
|
|
378
|
+
/**
|
|
379
|
+
* Release the lock
|
|
380
|
+
*/
|
|
381
|
+
unlock() {
|
|
382
|
+
this.locked = false;
|
|
383
|
+
}
|
|
384
|
+
/**
|
|
385
|
+
* Try to acquire the lock without blocking
|
|
386
|
+
*/
|
|
387
|
+
tryLock() {
|
|
388
|
+
if (this.locked) {
|
|
389
|
+
return false;
|
|
390
|
+
}
|
|
391
|
+
this.locked = true;
|
|
392
|
+
return true;
|
|
393
|
+
}
|
|
394
|
+
};
|
|
395
|
+
function hotPath() {
|
|
396
|
+
}
|
|
397
|
+
function coldPath() {
|
|
398
|
+
}
|
|
399
|
+
var MemoryOps = class {
|
|
400
|
+
/**
|
|
401
|
+
* Copy memory with potential SIMD optimization
|
|
402
|
+
*/
|
|
403
|
+
static memCopy(dst, src) {
|
|
404
|
+
const n = Math.min(dst.length, src.length);
|
|
405
|
+
dst.set(src.slice(0, n));
|
|
406
|
+
return n;
|
|
407
|
+
}
|
|
408
|
+
/**
|
|
409
|
+
* Set memory with potential SIMD optimization
|
|
410
|
+
*/
|
|
411
|
+
static memSet(dst, value) {
|
|
412
|
+
dst.fill(value);
|
|
413
|
+
}
|
|
414
|
+
/**
|
|
415
|
+
* Zero memory
|
|
416
|
+
*/
|
|
417
|
+
static memZero(dst) {
|
|
418
|
+
dst.fill(0);
|
|
419
|
+
}
|
|
420
|
+
};
|
|
421
|
+
function detectCPUFeatures() {
|
|
422
|
+
return {
|
|
423
|
+
hasSIMD: true,
|
|
424
|
+
// V8 has SIMD optimizations
|
|
425
|
+
hasAVX: false,
|
|
426
|
+
// Not detectable in JS
|
|
427
|
+
hasAVX2: false,
|
|
428
|
+
hasSSE: false,
|
|
429
|
+
hasSSE2: false,
|
|
430
|
+
hasSSE3: false,
|
|
431
|
+
hasSSE41: false,
|
|
432
|
+
hasSSE42: false,
|
|
433
|
+
hasFMA: false,
|
|
434
|
+
hasBMI: false,
|
|
435
|
+
hasBMI2: false,
|
|
436
|
+
hasPopcnt: false,
|
|
437
|
+
cacheLine: CACHE_LINE_SIZE,
|
|
438
|
+
numCPU: __require("os").cpus().length
|
|
439
|
+
};
|
|
440
|
+
}
|
|
441
|
+
var globalProfileOptimizer = null;
|
|
442
|
+
function getProfileOptimizer() {
|
|
443
|
+
if (!globalProfileOptimizer) {
|
|
444
|
+
globalProfileOptimizer = new ProfileGuidedOptimizer();
|
|
445
|
+
}
|
|
446
|
+
return globalProfileOptimizer;
|
|
447
|
+
}
|
|
448
|
+
function profile(target, propertyKey, descriptor) {
|
|
449
|
+
const original = descriptor.value;
|
|
450
|
+
const optimizer = getProfileOptimizer();
|
|
451
|
+
const name = `${target.constructor.name}.${propertyKey}`;
|
|
452
|
+
descriptor.value = optimizer.instrument(name, original);
|
|
453
|
+
return descriptor;
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
// src/perf/hardware.ts
|
|
457
|
+
function defaultAffinityConfig() {
|
|
458
|
+
return {
|
|
459
|
+
enablePinning: false,
|
|
460
|
+
preferredCores: [],
|
|
461
|
+
avoidSMT: true,
|
|
462
|
+
numaNode: 0
|
|
463
|
+
};
|
|
464
|
+
}
|
|
465
|
+
function defaultNUMAConfig() {
|
|
466
|
+
return {
|
|
467
|
+
enableNUMA: false,
|
|
468
|
+
preferredNode: 0,
|
|
469
|
+
interleave: false
|
|
470
|
+
};
|
|
471
|
+
}
|
|
472
|
+
var CPUAffinity = class {
|
|
473
|
+
config;
|
|
474
|
+
pinnedCores = /* @__PURE__ */ new Set();
|
|
475
|
+
constructor(config = defaultAffinityConfig()) {
|
|
476
|
+
this.config = config;
|
|
477
|
+
}
|
|
478
|
+
/**
|
|
479
|
+
* Get CPU topology information
|
|
480
|
+
*/
|
|
481
|
+
getTopology() {
|
|
482
|
+
const os = __require("os");
|
|
483
|
+
const cpus = os.cpus();
|
|
484
|
+
const logicalCores = cpus.length;
|
|
485
|
+
const physicalCores = Math.ceil(logicalCores / 2);
|
|
486
|
+
return {
|
|
487
|
+
physicalCores,
|
|
488
|
+
logicalCores,
|
|
489
|
+
numaNodes: 1,
|
|
490
|
+
// Node.js doesn't expose NUMA info
|
|
491
|
+
cacheLevels: [
|
|
492
|
+
{ level: 1, size: 32 * 1024, lineSize: 64, associativity: 8 },
|
|
493
|
+
{ level: 2, size: 256 * 1024, lineSize: 64, associativity: 8 },
|
|
494
|
+
{ level: 3, size: 8 * 1024 * 1024, lineSize: 64, associativity: 16 }
|
|
495
|
+
]
|
|
496
|
+
};
|
|
497
|
+
}
|
|
498
|
+
/**
|
|
499
|
+
* Pin current execution context to a specific core
|
|
500
|
+
* Note: In Node.js, this is advisory only via worker threads
|
|
501
|
+
*/
|
|
502
|
+
pinToCore(coreId) {
|
|
503
|
+
if (!this.config.enablePinning) {
|
|
504
|
+
return false;
|
|
505
|
+
}
|
|
506
|
+
this.pinnedCores.add(coreId);
|
|
507
|
+
return true;
|
|
508
|
+
}
|
|
509
|
+
/**
|
|
510
|
+
* Pin to multiple cores
|
|
511
|
+
*/
|
|
512
|
+
pinToCores(coreIds) {
|
|
513
|
+
if (!this.config.enablePinning) {
|
|
514
|
+
return false;
|
|
515
|
+
}
|
|
516
|
+
for (const coreId of coreIds) {
|
|
517
|
+
this.pinnedCores.add(coreId);
|
|
518
|
+
}
|
|
519
|
+
return true;
|
|
520
|
+
}
|
|
521
|
+
/**
|
|
522
|
+
* Get recommended cores for pinning
|
|
523
|
+
*/
|
|
524
|
+
getRecommendedCores(count = 1) {
|
|
525
|
+
const topology = this.getTopology();
|
|
526
|
+
const cores = [];
|
|
527
|
+
if (this.config.preferredCores.length > 0) {
|
|
528
|
+
for (let i = 0; i < count && i < this.config.preferredCores.length; i++) {
|
|
529
|
+
cores.push(this.config.preferredCores[i]);
|
|
530
|
+
}
|
|
531
|
+
} else {
|
|
532
|
+
const step = this.config.avoidSMT ? 2 : 1;
|
|
533
|
+
for (let i = 0; i < count * step && i < topology.physicalCores; i += step) {
|
|
534
|
+
cores.push(i);
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
return cores;
|
|
538
|
+
}
|
|
539
|
+
/**
|
|
540
|
+
* Check if a core is available
|
|
541
|
+
*/
|
|
542
|
+
isCoreAvailable(coreId) {
|
|
543
|
+
const topology = this.getTopology();
|
|
544
|
+
return coreId >= 0 && coreId < topology.logicalCores;
|
|
545
|
+
}
|
|
546
|
+
/**
|
|
547
|
+
* Get current core (simulated)
|
|
548
|
+
*/
|
|
549
|
+
getCurrentCore() {
|
|
550
|
+
return 0;
|
|
551
|
+
}
|
|
552
|
+
/**
|
|
553
|
+
* Get pinned cores
|
|
554
|
+
*/
|
|
555
|
+
getPinnedCores() {
|
|
556
|
+
return Array.from(this.pinnedCores);
|
|
557
|
+
}
|
|
558
|
+
/**
|
|
559
|
+
* Unpin all cores
|
|
560
|
+
*/
|
|
561
|
+
unpinAll() {
|
|
562
|
+
this.pinnedCores.clear();
|
|
563
|
+
}
|
|
564
|
+
};
|
|
565
|
+
var NUMAOptimizer = class {
|
|
566
|
+
config;
|
|
567
|
+
allocations = /* @__PURE__ */ new Map();
|
|
568
|
+
constructor(config = defaultNUMAConfig()) {
|
|
569
|
+
this.config = config;
|
|
570
|
+
}
|
|
571
|
+
/**
|
|
572
|
+
* Allocate memory with NUMA awareness
|
|
573
|
+
*/
|
|
574
|
+
allocate(size, tag = "default") {
|
|
575
|
+
const buffer = new ArrayBuffer(size);
|
|
576
|
+
this.allocations.set(tag, {
|
|
577
|
+
buffer,
|
|
578
|
+
size,
|
|
579
|
+
node: this.config.preferredNode,
|
|
580
|
+
timestamp: Date.now()
|
|
581
|
+
});
|
|
582
|
+
return buffer;
|
|
583
|
+
}
|
|
584
|
+
/**
|
|
585
|
+
* Allocate typed array with NUMA awareness
|
|
586
|
+
*/
|
|
587
|
+
allocateTypedArray(constructor, length, tag = "default") {
|
|
588
|
+
const bytesPerElement = constructor.BYTES_PER_ELEMENT;
|
|
589
|
+
const buffer = this.allocate(length * bytesPerElement, tag);
|
|
590
|
+
return new constructor(buffer);
|
|
591
|
+
}
|
|
592
|
+
/**
|
|
593
|
+
* Get allocation information
|
|
594
|
+
*/
|
|
595
|
+
getAllocation(tag) {
|
|
596
|
+
return this.allocations.get(tag);
|
|
597
|
+
}
|
|
598
|
+
/**
|
|
599
|
+
* Get local memory node for current thread
|
|
600
|
+
*/
|
|
601
|
+
getLocalNode() {
|
|
602
|
+
return this.config.preferredNode;
|
|
603
|
+
}
|
|
604
|
+
/**
|
|
605
|
+
* Get number of NUMA nodes
|
|
606
|
+
*/
|
|
607
|
+
getNodeCount() {
|
|
608
|
+
return 1;
|
|
609
|
+
}
|
|
610
|
+
/**
|
|
611
|
+
* Check if NUMA is available
|
|
612
|
+
*/
|
|
613
|
+
isNUMAAvailable() {
|
|
614
|
+
return false;
|
|
615
|
+
}
|
|
616
|
+
/**
|
|
617
|
+
* Migrate allocation to preferred node
|
|
618
|
+
* Note: No-op in JavaScript
|
|
619
|
+
*/
|
|
620
|
+
migrateToNode(tag, node) {
|
|
621
|
+
const allocation = this.allocations.get(tag);
|
|
622
|
+
if (!allocation) {
|
|
623
|
+
return false;
|
|
624
|
+
}
|
|
625
|
+
allocation.node = node;
|
|
626
|
+
return true;
|
|
627
|
+
}
|
|
628
|
+
/**
|
|
629
|
+
* Free allocation tracking
|
|
630
|
+
*/
|
|
631
|
+
free(tag) {
|
|
632
|
+
this.allocations.delete(tag);
|
|
633
|
+
}
|
|
634
|
+
/**
|
|
635
|
+
* Get all allocations
|
|
636
|
+
*/
|
|
637
|
+
getAllAllocations() {
|
|
638
|
+
return new Map(this.allocations);
|
|
639
|
+
}
|
|
640
|
+
};
|
|
641
|
+
var CacheOptimizer = class {
|
|
642
|
+
cacheLineSize = 64;
|
|
643
|
+
l1Size = 32 * 1024;
|
|
644
|
+
l2Size = 256 * 1024;
|
|
645
|
+
l3Size = 8 * 1024 * 1024;
|
|
646
|
+
constructor() {
|
|
647
|
+
}
|
|
648
|
+
/**
|
|
649
|
+
* Set cache parameters
|
|
650
|
+
*/
|
|
651
|
+
setCacheParams(params) {
|
|
652
|
+
if (params.cacheLineSize) this.cacheLineSize = params.cacheLineSize;
|
|
653
|
+
if (params.l1Size) this.l1Size = params.l1Size;
|
|
654
|
+
if (params.l2Size) this.l2Size = params.l2Size;
|
|
655
|
+
if (params.l3Size) this.l3Size = params.l3Size;
|
|
656
|
+
}
|
|
657
|
+
/**
|
|
658
|
+
* Align size to cache line boundary
|
|
659
|
+
*/
|
|
660
|
+
alignToCacheLine(size) {
|
|
661
|
+
const mask = this.cacheLineSize - 1;
|
|
662
|
+
return size + mask & ~mask;
|
|
663
|
+
}
|
|
664
|
+
/**
|
|
665
|
+
* Check if address is cache line aligned
|
|
666
|
+
*/
|
|
667
|
+
isCacheLineAligned(address) {
|
|
668
|
+
return (address & this.cacheLineSize - 1) === 0;
|
|
669
|
+
}
|
|
670
|
+
/**
|
|
671
|
+
* Calculate cache-friendly array stride
|
|
672
|
+
*/
|
|
673
|
+
calculateStride(elementSize) {
|
|
674
|
+
return Math.max(elementSize, this.cacheLineSize);
|
|
675
|
+
}
|
|
676
|
+
/**
|
|
677
|
+
* Create cache-friendly layout for array of objects
|
|
678
|
+
*/
|
|
679
|
+
createSoALayout(count, schema) {
|
|
680
|
+
const typeSizes = {
|
|
681
|
+
u8: 1,
|
|
682
|
+
u16: 2,
|
|
683
|
+
u32: 4,
|
|
684
|
+
u64: 8,
|
|
685
|
+
f32: 4,
|
|
686
|
+
f64: 8
|
|
687
|
+
};
|
|
688
|
+
const arrays = {};
|
|
689
|
+
const offsets = {};
|
|
690
|
+
let currentOffset = 0;
|
|
691
|
+
for (const [key, type] of Object.entries(schema)) {
|
|
692
|
+
const size = typeSizes[type];
|
|
693
|
+
if (size === void 0) {
|
|
694
|
+
throw new Error(`Unsupported struct field type: ${type}`);
|
|
695
|
+
}
|
|
696
|
+
const alignedOffset = this.alignToCacheLine(currentOffset);
|
|
697
|
+
offsets[key] = alignedOffset;
|
|
698
|
+
const totalSize = alignedOffset + count * size;
|
|
699
|
+
const buffer = new ArrayBuffer(totalSize);
|
|
700
|
+
switch (type) {
|
|
701
|
+
case "u8":
|
|
702
|
+
arrays[key] = new Uint8Array(buffer, alignedOffset, count);
|
|
703
|
+
break;
|
|
704
|
+
case "u16":
|
|
705
|
+
arrays[key] = new Uint16Array(buffer, alignedOffset, count);
|
|
706
|
+
break;
|
|
707
|
+
case "u32":
|
|
708
|
+
arrays[key] = new Uint32Array(buffer, alignedOffset, count);
|
|
709
|
+
break;
|
|
710
|
+
case "u64":
|
|
711
|
+
arrays[key] = new BigUint64Array(buffer, alignedOffset, count);
|
|
712
|
+
break;
|
|
713
|
+
case "f32":
|
|
714
|
+
arrays[key] = new Float32Array(buffer, alignedOffset, count);
|
|
715
|
+
break;
|
|
716
|
+
case "f64":
|
|
717
|
+
arrays[key] = new Float64Array(buffer, alignedOffset, count);
|
|
718
|
+
break;
|
|
719
|
+
}
|
|
720
|
+
currentOffset = alignedOffset + count * size;
|
|
721
|
+
}
|
|
722
|
+
return {
|
|
723
|
+
arrays,
|
|
724
|
+
offsets,
|
|
725
|
+
count,
|
|
726
|
+
get(index) {
|
|
727
|
+
const result = {};
|
|
728
|
+
for (const key of Object.keys(arrays)) {
|
|
729
|
+
result[key] = arrays[key][index];
|
|
730
|
+
}
|
|
731
|
+
return result;
|
|
732
|
+
},
|
|
733
|
+
set(index, value) {
|
|
734
|
+
for (const key of Object.keys(arrays)) {
|
|
735
|
+
arrays[key][index] = value[key];
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
};
|
|
739
|
+
}
|
|
740
|
+
/**
|
|
741
|
+
* Get cache line size
|
|
742
|
+
*/
|
|
743
|
+
getCacheLineSize() {
|
|
744
|
+
return this.cacheLineSize;
|
|
745
|
+
}
|
|
746
|
+
/**
|
|
747
|
+
* Get L1 cache size
|
|
748
|
+
*/
|
|
749
|
+
getL1Size() {
|
|
750
|
+
return this.l1Size;
|
|
751
|
+
}
|
|
752
|
+
/**
|
|
753
|
+
* Get L2 cache size
|
|
754
|
+
*/
|
|
755
|
+
getL2Size() {
|
|
756
|
+
return this.l2Size;
|
|
757
|
+
}
|
|
758
|
+
/**
|
|
759
|
+
* Get L3 cache size
|
|
760
|
+
*/
|
|
761
|
+
getL3Size() {
|
|
762
|
+
return this.l3Size;
|
|
763
|
+
}
|
|
764
|
+
};
|
|
765
|
+
var HardwareMonitor = class {
|
|
766
|
+
startTime = 0;
|
|
767
|
+
measurements = [];
|
|
768
|
+
/**
|
|
769
|
+
* Start monitoring
|
|
770
|
+
*/
|
|
771
|
+
start() {
|
|
772
|
+
this.startTime = performance.now();
|
|
773
|
+
}
|
|
774
|
+
/**
|
|
775
|
+
* Take a measurement
|
|
776
|
+
*/
|
|
777
|
+
measure(label) {
|
|
778
|
+
this.measurements.push({
|
|
779
|
+
label,
|
|
780
|
+
timestamp: performance.now() - this.startTime,
|
|
781
|
+
memory: this.getMemoryInfo()
|
|
782
|
+
});
|
|
783
|
+
}
|
|
784
|
+
/**
|
|
785
|
+
* Get memory information
|
|
786
|
+
*/
|
|
787
|
+
getMemoryInfo() {
|
|
788
|
+
if (typeof process !== "undefined" && process.memoryUsage) {
|
|
789
|
+
const usage = process.memoryUsage();
|
|
790
|
+
return {
|
|
791
|
+
used: usage.heapUsed,
|
|
792
|
+
total: usage.heapTotal,
|
|
793
|
+
external: usage.external,
|
|
794
|
+
rss: usage.rss
|
|
795
|
+
};
|
|
796
|
+
}
|
|
797
|
+
if (typeof performance !== "undefined" && performance.memory) {
|
|
798
|
+
const mem = performance.memory;
|
|
799
|
+
return {
|
|
800
|
+
used: mem.usedJSHeapSize,
|
|
801
|
+
total: mem.totalJSHeapSize,
|
|
802
|
+
external: 0,
|
|
803
|
+
rss: 0
|
|
804
|
+
};
|
|
805
|
+
}
|
|
806
|
+
return { used: 0, total: 0, external: 0, rss: 0 };
|
|
807
|
+
}
|
|
808
|
+
/**
|
|
809
|
+
* Get all measurements
|
|
810
|
+
*/
|
|
811
|
+
getMeasurements() {
|
|
812
|
+
return [...this.measurements];
|
|
813
|
+
}
|
|
814
|
+
/**
|
|
815
|
+
* Reset measurements
|
|
816
|
+
*/
|
|
817
|
+
reset() {
|
|
818
|
+
this.measurements = [];
|
|
819
|
+
this.startTime = performance.now();
|
|
820
|
+
}
|
|
821
|
+
};
|
|
822
|
+
function createCPUAffinity(config) {
|
|
823
|
+
const fullConfig = { ...defaultAffinityConfig(), ...config };
|
|
824
|
+
return new CPUAffinity(fullConfig);
|
|
825
|
+
}
|
|
826
|
+
function createNUMAOptimizer(config) {
|
|
827
|
+
const fullConfig = { ...defaultNUMAConfig(), ...config };
|
|
828
|
+
return new NUMAOptimizer(fullConfig);
|
|
829
|
+
}
|
|
830
|
+
function createCacheOptimizer() {
|
|
831
|
+
return new CacheOptimizer();
|
|
832
|
+
}
|
|
833
|
+
function createHardwareMonitor() {
|
|
834
|
+
return new HardwareMonitor();
|
|
835
|
+
}
|
|
836
|
+
function getSystemCPUInfo() {
|
|
837
|
+
const os = __require("os");
|
|
838
|
+
const cpus = os.cpus();
|
|
839
|
+
return {
|
|
840
|
+
cores: cpus.length,
|
|
841
|
+
model: cpus[0]?.model || "Unknown"
|
|
842
|
+
};
|
|
843
|
+
}
|
|
844
|
+
function getSystemMemoryInfo() {
|
|
845
|
+
const os = __require("os");
|
|
846
|
+
return {
|
|
847
|
+
total: os.totalmem(),
|
|
848
|
+
free: os.freemem()
|
|
849
|
+
};
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
// src/perf/kernel-bypass.ts
|
|
853
|
+
var IOOperation = /* @__PURE__ */ ((IOOperation2) => {
|
|
854
|
+
IOOperation2["READ"] = "READ";
|
|
855
|
+
IOOperation2["WRITE"] = "WRITE";
|
|
856
|
+
IOOperation2["FSYNC"] = "FSYNC";
|
|
857
|
+
IOOperation2["POLL"] = "POLL";
|
|
858
|
+
IOOperation2["TIMEOUT"] = "TIMEOUT";
|
|
859
|
+
return IOOperation2;
|
|
860
|
+
})(IOOperation || {});
|
|
861
|
+
function defaultIOUringConfig() {
|
|
862
|
+
return {
|
|
863
|
+
queueDepth: 256,
|
|
864
|
+
sqThreadIdle: 2e3,
|
|
865
|
+
sqThreadCpu: -1,
|
|
866
|
+
cqSize: 0,
|
|
867
|
+
flags: 0,
|
|
868
|
+
features: []
|
|
869
|
+
};
|
|
870
|
+
}
|
|
871
|
+
var KernelBypassManager = class {
|
|
872
|
+
config;
|
|
873
|
+
uringAvailable = false;
|
|
874
|
+
requestCounter = 0;
|
|
875
|
+
pendingRequests = /* @__PURE__ */ new Map();
|
|
876
|
+
running = false;
|
|
877
|
+
processTimer = null;
|
|
878
|
+
constructor(config) {
|
|
879
|
+
this.config = config || defaultIOUringConfig();
|
|
880
|
+
this.checkUringAvailability();
|
|
881
|
+
}
|
|
882
|
+
/**
|
|
883
|
+
* Check if io_uring-like functionality is available
|
|
884
|
+
*/
|
|
885
|
+
checkUringAvailability() {
|
|
886
|
+
if (process.platform !== "linux") {
|
|
887
|
+
return false;
|
|
888
|
+
}
|
|
889
|
+
this.uringAvailable = false;
|
|
890
|
+
return false;
|
|
891
|
+
}
|
|
892
|
+
/**
|
|
893
|
+
* Check if io_uring is available
|
|
894
|
+
*/
|
|
895
|
+
isUringAvailable() {
|
|
896
|
+
return this.uringAvailable;
|
|
897
|
+
}
|
|
898
|
+
/**
|
|
899
|
+
* Start the I/O processing loop
|
|
900
|
+
*/
|
|
901
|
+
start() {
|
|
902
|
+
if (this.running) return;
|
|
903
|
+
this.running = true;
|
|
904
|
+
this.processTimer = setInterval(() => {
|
|
905
|
+
this.processPendingRequests();
|
|
906
|
+
}, 0.1);
|
|
907
|
+
setImmediate(() => this.processLoop());
|
|
908
|
+
}
|
|
909
|
+
/**
|
|
910
|
+
* Stop the I/O processing loop
|
|
911
|
+
*/
|
|
912
|
+
stop() {
|
|
913
|
+
this.running = false;
|
|
914
|
+
if (this.processTimer) {
|
|
915
|
+
clearInterval(this.processTimer);
|
|
916
|
+
this.processTimer = null;
|
|
917
|
+
}
|
|
918
|
+
}
|
|
919
|
+
/**
|
|
920
|
+
* Main processing loop
|
|
921
|
+
*/
|
|
922
|
+
processLoop() {
|
|
923
|
+
if (!this.running) return;
|
|
924
|
+
this.processPendingRequests();
|
|
925
|
+
if (this.running) {
|
|
926
|
+
setImmediate(() => this.processLoop());
|
|
927
|
+
}
|
|
928
|
+
}
|
|
929
|
+
/**
|
|
930
|
+
* Process pending I/O requests
|
|
931
|
+
*/
|
|
932
|
+
processPendingRequests() {
|
|
933
|
+
const toDelete = [];
|
|
934
|
+
this.pendingRequests.forEach((request, id) => {
|
|
935
|
+
switch (request.op) {
|
|
936
|
+
case "READ" /* READ */:
|
|
937
|
+
this.processRead(id, request);
|
|
938
|
+
break;
|
|
939
|
+
case "WRITE" /* WRITE */:
|
|
940
|
+
this.processWrite(id, request);
|
|
941
|
+
break;
|
|
942
|
+
}
|
|
943
|
+
toDelete.push(id);
|
|
944
|
+
});
|
|
945
|
+
toDelete.forEach((id) => this.pendingRequests.delete(id));
|
|
946
|
+
}
|
|
947
|
+
/**
|
|
948
|
+
* Process a read request
|
|
949
|
+
*/
|
|
950
|
+
processRead(id, request) {
|
|
951
|
+
try {
|
|
952
|
+
const fs = __require("fs");
|
|
953
|
+
const buffer = Buffer.alloc(request.size);
|
|
954
|
+
fs.read(request.fd, buffer, 0, request.size, request.offset, (err, bytesRead) => {
|
|
955
|
+
if (request.callback) {
|
|
956
|
+
request.callback(id, err ? null : buffer.slice(0, bytesRead), bytesRead);
|
|
957
|
+
}
|
|
958
|
+
});
|
|
959
|
+
} catch (error) {
|
|
960
|
+
if (request.callback) {
|
|
961
|
+
request.callback(id, null, 0);
|
|
962
|
+
}
|
|
963
|
+
}
|
|
964
|
+
}
|
|
965
|
+
/**
|
|
966
|
+
* Process a write request
|
|
967
|
+
*/
|
|
968
|
+
processWrite(id, request) {
|
|
969
|
+
try {
|
|
970
|
+
const fs = __require("fs");
|
|
971
|
+
fs.write(request.fd, request.buffer, 0, request.buffer.length, request.offset, (err, bytesWritten) => {
|
|
972
|
+
if (request.callback) {
|
|
973
|
+
request.callback(id, null, bytesWritten);
|
|
974
|
+
}
|
|
975
|
+
});
|
|
976
|
+
} catch (error) {
|
|
977
|
+
if (request.callback) {
|
|
978
|
+
request.callback(id, null, 0);
|
|
979
|
+
}
|
|
980
|
+
}
|
|
981
|
+
}
|
|
982
|
+
/**
|
|
983
|
+
* Submit an async read request
|
|
984
|
+
*/
|
|
985
|
+
submitRead(fd, size, offset = 0, callback, userData) {
|
|
986
|
+
const id = ++this.requestCounter;
|
|
987
|
+
const request = {
|
|
988
|
+
op: "READ" /* READ */,
|
|
989
|
+
fd,
|
|
990
|
+
offset,
|
|
991
|
+
size,
|
|
992
|
+
callback,
|
|
993
|
+
userData
|
|
994
|
+
};
|
|
995
|
+
this.pendingRequests.set(id, request);
|
|
996
|
+
return id;
|
|
997
|
+
}
|
|
998
|
+
/**
|
|
999
|
+
* Submit an async write request
|
|
1000
|
+
*/
|
|
1001
|
+
submitWrite(fd, buffer, offset = 0, callback, userData) {
|
|
1002
|
+
const id = ++this.requestCounter;
|
|
1003
|
+
const request = {
|
|
1004
|
+
op: "WRITE" /* WRITE */,
|
|
1005
|
+
fd,
|
|
1006
|
+
buffer,
|
|
1007
|
+
offset,
|
|
1008
|
+
size: buffer.length,
|
|
1009
|
+
callback,
|
|
1010
|
+
userData
|
|
1011
|
+
};
|
|
1012
|
+
this.pendingRequests.set(id, request);
|
|
1013
|
+
return id;
|
|
1014
|
+
}
|
|
1015
|
+
};
|
|
1016
|
+
var DirectIOFile = class {
|
|
1017
|
+
path;
|
|
1018
|
+
fd = null;
|
|
1019
|
+
directIO = false;
|
|
1020
|
+
constructor(path) {
|
|
1021
|
+
this.path = path;
|
|
1022
|
+
}
|
|
1023
|
+
/**
|
|
1024
|
+
* Open file with direct I/O if available
|
|
1025
|
+
*/
|
|
1026
|
+
async open() {
|
|
1027
|
+
const fs = __require("fs").promises;
|
|
1028
|
+
try {
|
|
1029
|
+
this.fd = await fs.open(this.path, "r+");
|
|
1030
|
+
this.directIO = process.platform === "linux";
|
|
1031
|
+
return true;
|
|
1032
|
+
} catch (error) {
|
|
1033
|
+
try {
|
|
1034
|
+
this.fd = await fs.open(this.path, "w+");
|
|
1035
|
+
return true;
|
|
1036
|
+
} catch {
|
|
1037
|
+
return false;
|
|
1038
|
+
}
|
|
1039
|
+
}
|
|
1040
|
+
}
|
|
1041
|
+
/**
|
|
1042
|
+
* Close the file
|
|
1043
|
+
*/
|
|
1044
|
+
async close() {
|
|
1045
|
+
if (this.fd !== null) {
|
|
1046
|
+
const fs = __require("fs").promises;
|
|
1047
|
+
await fs.close(this.fd);
|
|
1048
|
+
this.fd = null;
|
|
1049
|
+
}
|
|
1050
|
+
}
|
|
1051
|
+
/**
|
|
1052
|
+
* Read from file
|
|
1053
|
+
*/
|
|
1054
|
+
async read(size, offset = 0) {
|
|
1055
|
+
if (this.fd === null) {
|
|
1056
|
+
throw new Error("File not open");
|
|
1057
|
+
}
|
|
1058
|
+
if (this.directIO) {
|
|
1059
|
+
return this.readDirect(size, offset);
|
|
1060
|
+
}
|
|
1061
|
+
const fs = __require("fs").promises;
|
|
1062
|
+
const buffer = Buffer.alloc(size);
|
|
1063
|
+
await fs.read(this.fd, buffer, 0, size, offset);
|
|
1064
|
+
return buffer;
|
|
1065
|
+
}
|
|
1066
|
+
/**
|
|
1067
|
+
* Read using direct I/O with aligned buffer
|
|
1068
|
+
*/
|
|
1069
|
+
async readDirect(size, offset) {
|
|
1070
|
+
const align = 512;
|
|
1071
|
+
const alignedOffset = Math.floor(offset / align) * align;
|
|
1072
|
+
const offsetDiff = offset - alignedOffset;
|
|
1073
|
+
const alignedSize = Math.ceil((size + offsetDiff + align - 1) / align) * align;
|
|
1074
|
+
const buffer = Buffer.alloc(alignedSize);
|
|
1075
|
+
const fs = __require("fs").promises;
|
|
1076
|
+
await fs.read(this.fd, buffer, 0, alignedSize, alignedOffset);
|
|
1077
|
+
return buffer.slice(offsetDiff, offsetDiff + size);
|
|
1078
|
+
}
|
|
1079
|
+
/**
|
|
1080
|
+
* Write to file
|
|
1081
|
+
*/
|
|
1082
|
+
async write(data, offset = 0) {
|
|
1083
|
+
if (this.fd === null) {
|
|
1084
|
+
throw new Error("File not open");
|
|
1085
|
+
}
|
|
1086
|
+
const fs = __require("fs").promises;
|
|
1087
|
+
const { bytesWritten } = await fs.write(this.fd, data, 0, data.length, offset);
|
|
1088
|
+
return bytesWritten;
|
|
1089
|
+
}
|
|
1090
|
+
/**
|
|
1091
|
+
* Sync file to disk
|
|
1092
|
+
*/
|
|
1093
|
+
async fsync() {
|
|
1094
|
+
if (this.fd !== null) {
|
|
1095
|
+
const fs = __require("fs").promises;
|
|
1096
|
+
await fs.fsync(this.fd);
|
|
1097
|
+
}
|
|
1098
|
+
}
|
|
1099
|
+
};
|
|
1100
|
+
var MemoryMappedFile = class {
|
|
1101
|
+
path;
|
|
1102
|
+
fd = null;
|
|
1103
|
+
buffer = null;
|
|
1104
|
+
constructor(path) {
|
|
1105
|
+
this.path = path;
|
|
1106
|
+
}
|
|
1107
|
+
/**
|
|
1108
|
+
* Open and memory-map the file
|
|
1109
|
+
*/
|
|
1110
|
+
async open(size = 0) {
|
|
1111
|
+
const fs = __require("fs");
|
|
1112
|
+
const fsPromises = fs.promises;
|
|
1113
|
+
try {
|
|
1114
|
+
const fileHandle = await fsPromises.open(this.path, "r+");
|
|
1115
|
+
this.fd = fileHandle.fd;
|
|
1116
|
+
const stats = await fileHandle.stat();
|
|
1117
|
+
let fileSize = stats.size;
|
|
1118
|
+
if (size > 0 && size > fileSize) {
|
|
1119
|
+
await fileHandle.truncate(size);
|
|
1120
|
+
fileSize = size;
|
|
1121
|
+
}
|
|
1122
|
+
if (fileSize === 0) {
|
|
1123
|
+
fileSize = 4096;
|
|
1124
|
+
await fileHandle.truncate(fileSize);
|
|
1125
|
+
}
|
|
1126
|
+
this.buffer = Buffer.alloc(fileSize);
|
|
1127
|
+
await fileHandle.read(this.buffer, 0, fileSize, 0);
|
|
1128
|
+
return true;
|
|
1129
|
+
} catch (error) {
|
|
1130
|
+
return false;
|
|
1131
|
+
}
|
|
1132
|
+
}
|
|
1133
|
+
/**
|
|
1134
|
+
* Close the memory-mapped file
|
|
1135
|
+
*/
|
|
1136
|
+
async close() {
|
|
1137
|
+
if (this.buffer) {
|
|
1138
|
+
const fs = __require("fs").promises;
|
|
1139
|
+
if (this.fd !== null) {
|
|
1140
|
+
await fs.write(this.fd, this.buffer, 0, this.buffer.length, 0);
|
|
1141
|
+
}
|
|
1142
|
+
this.buffer = null;
|
|
1143
|
+
}
|
|
1144
|
+
if (this.fd !== null) {
|
|
1145
|
+
const fs = __require("fs").promises;
|
|
1146
|
+
await fs.close(this.fd);
|
|
1147
|
+
this.fd = null;
|
|
1148
|
+
}
|
|
1149
|
+
}
|
|
1150
|
+
/**
|
|
1151
|
+
* Read from memory-mapped file
|
|
1152
|
+
*/
|
|
1153
|
+
read(offset, size) {
|
|
1154
|
+
if (!this.buffer) {
|
|
1155
|
+
throw new Error("File not mapped");
|
|
1156
|
+
}
|
|
1157
|
+
return this.buffer.slice(offset, offset + size);
|
|
1158
|
+
}
|
|
1159
|
+
/**
|
|
1160
|
+
* Write to memory-mapped file
|
|
1161
|
+
*/
|
|
1162
|
+
write(offset, data) {
|
|
1163
|
+
if (!this.buffer) {
|
|
1164
|
+
throw new Error("File not mapped");
|
|
1165
|
+
}
|
|
1166
|
+
data.copy(this.buffer, offset);
|
|
1167
|
+
}
|
|
1168
|
+
/**
|
|
1169
|
+
* Flush changes to disk
|
|
1170
|
+
*/
|
|
1171
|
+
async flush() {
|
|
1172
|
+
if (this.buffer && this.fd !== null) {
|
|
1173
|
+
const fs = __require("fs").promises;
|
|
1174
|
+
await fs.write(this.fd, this.buffer, 0, this.buffer.length, 0);
|
|
1175
|
+
}
|
|
1176
|
+
}
|
|
1177
|
+
};
|
|
1178
|
+
var AsyncSocket = class {
|
|
1179
|
+
socket = null;
|
|
1180
|
+
/**
|
|
1181
|
+
* Set the underlying socket
|
|
1182
|
+
*/
|
|
1183
|
+
setSocket(socket) {
|
|
1184
|
+
this.socket = socket;
|
|
1185
|
+
}
|
|
1186
|
+
/**
|
|
1187
|
+
* Enable kernel bypass optimizations for this socket
|
|
1188
|
+
*/
|
|
1189
|
+
enableKernelBypass() {
|
|
1190
|
+
if (!this.socket) {
|
|
1191
|
+
return false;
|
|
1192
|
+
}
|
|
1193
|
+
try {
|
|
1194
|
+
this.socket.setNoDelay(true);
|
|
1195
|
+
this.socket.setKeepAlive(true, 1e3);
|
|
1196
|
+
return true;
|
|
1197
|
+
} catch (error) {
|
|
1198
|
+
return false;
|
|
1199
|
+
}
|
|
1200
|
+
}
|
|
1201
|
+
/**
|
|
1202
|
+
* Async receive with optimization
|
|
1203
|
+
*/
|
|
1204
|
+
async recv(size) {
|
|
1205
|
+
return new Promise((resolve, reject) => {
|
|
1206
|
+
if (!this.socket) {
|
|
1207
|
+
reject(new Error("Socket not set"));
|
|
1208
|
+
return;
|
|
1209
|
+
}
|
|
1210
|
+
this.socket.once("data", (data) => {
|
|
1211
|
+
resolve(data);
|
|
1212
|
+
});
|
|
1213
|
+
this.socket.once("error", reject);
|
|
1214
|
+
});
|
|
1215
|
+
}
|
|
1216
|
+
/**
|
|
1217
|
+
* Async send with optimization
|
|
1218
|
+
*/
|
|
1219
|
+
async send(data) {
|
|
1220
|
+
return new Promise((resolve, reject) => {
|
|
1221
|
+
if (!this.socket) {
|
|
1222
|
+
reject(new Error("Socket not set"));
|
|
1223
|
+
return;
|
|
1224
|
+
}
|
|
1225
|
+
this.socket.write(data, (err) => {
|
|
1226
|
+
if (err) {
|
|
1227
|
+
reject(err);
|
|
1228
|
+
} else {
|
|
1229
|
+
resolve();
|
|
1230
|
+
}
|
|
1231
|
+
});
|
|
1232
|
+
});
|
|
1233
|
+
}
|
|
1234
|
+
};
|
|
1235
|
+
var IOBatchProcessor = class {
|
|
1236
|
+
maxBatchSize;
|
|
1237
|
+
readBatch = [];
|
|
1238
|
+
writeBatch = [];
|
|
1239
|
+
manager;
|
|
1240
|
+
constructor(maxBatchSize = 32) {
|
|
1241
|
+
this.maxBatchSize = maxBatchSize;
|
|
1242
|
+
this.manager = new KernelBypassManager();
|
|
1243
|
+
}
|
|
1244
|
+
/**
|
|
1245
|
+
* Add read to batch
|
|
1246
|
+
*/
|
|
1247
|
+
addRead(fd, size, offset = 0, callback = () => {
|
|
1248
|
+
}) {
|
|
1249
|
+
this.readBatch.push({ fd, size, offset, callback });
|
|
1250
|
+
if (this.readBatch.length >= this.maxBatchSize) {
|
|
1251
|
+
this.flushReads();
|
|
1252
|
+
}
|
|
1253
|
+
}
|
|
1254
|
+
/**
|
|
1255
|
+
* Add write to batch
|
|
1256
|
+
*/
|
|
1257
|
+
addWrite(fd, data, offset = 0, callback = () => {
|
|
1258
|
+
}) {
|
|
1259
|
+
this.writeBatch.push({ fd, data, offset, callback });
|
|
1260
|
+
if (this.writeBatch.length >= this.maxBatchSize) {
|
|
1261
|
+
this.flushWrites();
|
|
1262
|
+
}
|
|
1263
|
+
}
|
|
1264
|
+
/**
|
|
1265
|
+
* Flush all pending reads
|
|
1266
|
+
*/
|
|
1267
|
+
flushReads() {
|
|
1268
|
+
if (this.readBatch.length === 0) {
|
|
1269
|
+
return [];
|
|
1270
|
+
}
|
|
1271
|
+
const requestIds = this.readBatch.map(
|
|
1272
|
+
(req) => this.manager.submitRead(req.fd, req.size, req.offset, req.callback)
|
|
1273
|
+
);
|
|
1274
|
+
this.readBatch = [];
|
|
1275
|
+
return requestIds;
|
|
1276
|
+
}
|
|
1277
|
+
/**
|
|
1278
|
+
* Flush all pending writes
|
|
1279
|
+
*/
|
|
1280
|
+
flushWrites() {
|
|
1281
|
+
if (this.writeBatch.length === 0) {
|
|
1282
|
+
return [];
|
|
1283
|
+
}
|
|
1284
|
+
const requestIds = this.writeBatch.map(
|
|
1285
|
+
(req) => this.manager.submitWrite(req.fd, req.data, req.offset, req.callback)
|
|
1286
|
+
);
|
|
1287
|
+
this.writeBatch = [];
|
|
1288
|
+
return requestIds;
|
|
1289
|
+
}
|
|
1290
|
+
/**
|
|
1291
|
+
* Flush all pending operations
|
|
1292
|
+
*/
|
|
1293
|
+
flushAll() {
|
|
1294
|
+
return {
|
|
1295
|
+
readIds: this.flushReads(),
|
|
1296
|
+
writeIds: this.flushWrites()
|
|
1297
|
+
};
|
|
1298
|
+
}
|
|
1299
|
+
};
|
|
1300
|
+
var globalKBManager = null;
|
|
1301
|
+
function getKernelBypassManager(config) {
|
|
1302
|
+
if (!globalKBManager) {
|
|
1303
|
+
globalKBManager = new KernelBypassManager(config);
|
|
1304
|
+
}
|
|
1305
|
+
return globalKBManager;
|
|
1306
|
+
}
|
|
1307
|
+
|
|
1308
|
+
// src/perf/protocol.ts
|
|
1309
|
+
import { ComputeBudgetProgram } from "@solana/web3.js";
|
|
1310
|
+
function defaultTransactionConfig() {
|
|
1311
|
+
return {
|
|
1312
|
+
computeUnitLimit: 2e5,
|
|
1313
|
+
computeUnitPrice: 1e5,
|
|
1314
|
+
priorityFee: 1e5,
|
|
1315
|
+
dynamicComputeBudget: true,
|
|
1316
|
+
packInstructions: true,
|
|
1317
|
+
maxTransactionSize: 1232,
|
|
1318
|
+
// Solana transaction size limit
|
|
1319
|
+
useAddressLookupTables: true
|
|
1320
|
+
};
|
|
1321
|
+
}
|
|
1322
|
+
var TransactionBuilder = class {
|
|
1323
|
+
instructions = [];
|
|
1324
|
+
config;
|
|
1325
|
+
computeEstimates = /* @__PURE__ */ new Map();
|
|
1326
|
+
signers = [];
|
|
1327
|
+
constructor(config = defaultTransactionConfig()) {
|
|
1328
|
+
this.config = config;
|
|
1329
|
+
this.initializeComputeEstimates();
|
|
1330
|
+
}
|
|
1331
|
+
/**
|
|
1332
|
+
* Initialize default compute estimates for common instructions
|
|
1333
|
+
*/
|
|
1334
|
+
initializeComputeEstimates() {
|
|
1335
|
+
this.computeEstimates.set("transfer", 450);
|
|
1336
|
+
this.computeEstimates.set("createAccount", 2500);
|
|
1337
|
+
this.computeEstimates.set("createATA", 3500);
|
|
1338
|
+
this.computeEstimates.set("closeAccount", 2500);
|
|
1339
|
+
this.computeEstimates.set("syncNative", 500);
|
|
1340
|
+
this.computeEstimates.set("setComputeUnitLimit", 100);
|
|
1341
|
+
this.computeEstimates.set("setComputeUnitPrice", 100);
|
|
1342
|
+
this.computeEstimates.set("pumpFunBuy", 45e3);
|
|
1343
|
+
this.computeEstimates.set("pumpFunSell", 4e4);
|
|
1344
|
+
this.computeEstimates.set("pumpSwapBuy", 5e4);
|
|
1345
|
+
this.computeEstimates.set("pumpSwapSell", 45e3);
|
|
1346
|
+
this.computeEstimates.set("raydiumSwap", 55e3);
|
|
1347
|
+
this.computeEstimates.set("meteoraSwap", 6e4);
|
|
1348
|
+
}
|
|
1349
|
+
/**
|
|
1350
|
+
* Add an instruction to the transaction
|
|
1351
|
+
*/
|
|
1352
|
+
addInstruction(instruction, computeEstimate, priority = 0) {
|
|
1353
|
+
this.instructions.push(instruction);
|
|
1354
|
+
for (const key of instruction.keys) {
|
|
1355
|
+
if (key.isSigner && !this.signers.some((s) => s.equals(key.pubkey))) {
|
|
1356
|
+
this.signers.push(key.pubkey);
|
|
1357
|
+
}
|
|
1358
|
+
}
|
|
1359
|
+
return this;
|
|
1360
|
+
}
|
|
1361
|
+
/**
|
|
1362
|
+
* Add multiple instructions
|
|
1363
|
+
*/
|
|
1364
|
+
addInstructions(instructions) {
|
|
1365
|
+
for (const ix of instructions) {
|
|
1366
|
+
this.addInstruction(ix);
|
|
1367
|
+
}
|
|
1368
|
+
return this;
|
|
1369
|
+
}
|
|
1370
|
+
/**
|
|
1371
|
+
* Add compute budget instructions
|
|
1372
|
+
*/
|
|
1373
|
+
addComputeBudget(units, price) {
|
|
1374
|
+
this.instructions.unshift(
|
|
1375
|
+
ComputeBudgetProgram.setComputeUnitLimit({ units }),
|
|
1376
|
+
ComputeBudgetProgram.setComputeUnitPrice({ microLamports: price })
|
|
1377
|
+
);
|
|
1378
|
+
return this;
|
|
1379
|
+
}
|
|
1380
|
+
/**
|
|
1381
|
+
* Estimate total compute units
|
|
1382
|
+
*/
|
|
1383
|
+
estimateCompute() {
|
|
1384
|
+
let total = 0;
|
|
1385
|
+
for (const ix of this.instructions) {
|
|
1386
|
+
const estimate = this.computeEstimates.get(ix.programId.toBase58()) || 3e3;
|
|
1387
|
+
total += estimate;
|
|
1388
|
+
}
|
|
1389
|
+
total += 200;
|
|
1390
|
+
return total;
|
|
1391
|
+
}
|
|
1392
|
+
/**
|
|
1393
|
+
* Build optimized transaction instructions
|
|
1394
|
+
*/
|
|
1395
|
+
build() {
|
|
1396
|
+
let optimizedInstructions = [...this.instructions];
|
|
1397
|
+
const optimizations = [];
|
|
1398
|
+
if (this.config.packInstructions) {
|
|
1399
|
+
optimizedInstructions = this.packInstructions(optimizedInstructions);
|
|
1400
|
+
optimizations.push("instruction_packing");
|
|
1401
|
+
}
|
|
1402
|
+
const computeEstimate = this.estimateCompute();
|
|
1403
|
+
let computeLimit = this.config.computeUnitLimit;
|
|
1404
|
+
if (this.config.dynamicComputeBudget) {
|
|
1405
|
+
computeLimit = this.calculateOptimalComputeLimit(computeEstimate);
|
|
1406
|
+
optimizations.push("dynamic_compute_budget");
|
|
1407
|
+
}
|
|
1408
|
+
const computePrice = this.calculateOptimalPrice();
|
|
1409
|
+
const estimatedSize = this.estimateTransactionSize(optimizedInstructions);
|
|
1410
|
+
optimizedInstructions = this.addComputeBudgetInstructions(
|
|
1411
|
+
optimizedInstructions,
|
|
1412
|
+
computeLimit,
|
|
1413
|
+
computePrice
|
|
1414
|
+
);
|
|
1415
|
+
return {
|
|
1416
|
+
instructions: optimizedInstructions,
|
|
1417
|
+
computeLimit,
|
|
1418
|
+
computePrice,
|
|
1419
|
+
estimatedSize,
|
|
1420
|
+
optimizations
|
|
1421
|
+
};
|
|
1422
|
+
}
|
|
1423
|
+
/**
|
|
1424
|
+
* Build and return only the instructions (without compute budget)
|
|
1425
|
+
*/
|
|
1426
|
+
buildInstructions() {
|
|
1427
|
+
return [...this.instructions];
|
|
1428
|
+
}
|
|
1429
|
+
/**
|
|
1430
|
+
* Clear all instructions
|
|
1431
|
+
*/
|
|
1432
|
+
clear() {
|
|
1433
|
+
this.instructions = [];
|
|
1434
|
+
this.signers = [];
|
|
1435
|
+
return this;
|
|
1436
|
+
}
|
|
1437
|
+
/**
|
|
1438
|
+
* Get current instruction count
|
|
1439
|
+
*/
|
|
1440
|
+
getInstructionCount() {
|
|
1441
|
+
return this.instructions.length;
|
|
1442
|
+
}
|
|
1443
|
+
/**
|
|
1444
|
+
* Get current signer count
|
|
1445
|
+
*/
|
|
1446
|
+
getSignerCount() {
|
|
1447
|
+
return this.signers.length;
|
|
1448
|
+
}
|
|
1449
|
+
packInstructions(instructions) {
|
|
1450
|
+
return instructions;
|
|
1451
|
+
}
|
|
1452
|
+
calculateOptimalComputeLimit(estimate) {
|
|
1453
|
+
const withBuffer = Math.ceil(estimate * 1.2);
|
|
1454
|
+
return Math.ceil(withBuffer / 1e4) * 1e4;
|
|
1455
|
+
}
|
|
1456
|
+
calculateOptimalPrice() {
|
|
1457
|
+
return this.config.computeUnitPrice;
|
|
1458
|
+
}
|
|
1459
|
+
estimateTransactionSize(instructions) {
|
|
1460
|
+
let size = 64;
|
|
1461
|
+
size += 3;
|
|
1462
|
+
size += 32 * (this.signers.length + 1);
|
|
1463
|
+
for (const ix of instructions) {
|
|
1464
|
+
size += 1;
|
|
1465
|
+
size += 1;
|
|
1466
|
+
size += ix.keys.length * 33;
|
|
1467
|
+
size += 2;
|
|
1468
|
+
size += ix.data.length;
|
|
1469
|
+
}
|
|
1470
|
+
return size;
|
|
1471
|
+
}
|
|
1472
|
+
addComputeBudgetInstructions(instructions, limit, price) {
|
|
1473
|
+
return instructions;
|
|
1474
|
+
}
|
|
1475
|
+
};
|
|
1476
|
+
var ComputeBudgetOptimizer = class {
|
|
1477
|
+
baseConfig;
|
|
1478
|
+
networkStats = {
|
|
1479
|
+
averageComputePrice: 0,
|
|
1480
|
+
congestionLevel: 0,
|
|
1481
|
+
recentSuccessRate: 1
|
|
1482
|
+
};
|
|
1483
|
+
history = [];
|
|
1484
|
+
maxHistorySize = 100;
|
|
1485
|
+
constructor(config = defaultTransactionConfig()) {
|
|
1486
|
+
this.baseConfig = config;
|
|
1487
|
+
}
|
|
1488
|
+
/**
|
|
1489
|
+
* Update network statistics
|
|
1490
|
+
*/
|
|
1491
|
+
updateNetworkStats(stats) {
|
|
1492
|
+
this.networkStats = { ...this.networkStats, ...stats };
|
|
1493
|
+
}
|
|
1494
|
+
/**
|
|
1495
|
+
* Get optimized compute budget for current conditions
|
|
1496
|
+
*/
|
|
1497
|
+
getOptimizedBudget(priority = "normal") {
|
|
1498
|
+
const multipliers = {
|
|
1499
|
+
low: 0.5,
|
|
1500
|
+
normal: 1,
|
|
1501
|
+
high: 2,
|
|
1502
|
+
critical: 5
|
|
1503
|
+
};
|
|
1504
|
+
const multiplier = multipliers[priority] ?? 1;
|
|
1505
|
+
const congestionMultiplier = 1 + this.networkStats.congestionLevel;
|
|
1506
|
+
const successMultiplier = this.networkStats.recentSuccessRate < 0.8 ? 1.5 : 1;
|
|
1507
|
+
const computeLimit = this.baseConfig.computeUnitLimit;
|
|
1508
|
+
const computePrice = Math.floor(
|
|
1509
|
+
this.baseConfig.computeUnitPrice * multiplier * congestionMultiplier * successMultiplier
|
|
1510
|
+
);
|
|
1511
|
+
const priorityFee = Math.floor(
|
|
1512
|
+
this.baseConfig.priorityFee * multiplier * congestionMultiplier * successMultiplier
|
|
1513
|
+
);
|
|
1514
|
+
return {
|
|
1515
|
+
computeLimit,
|
|
1516
|
+
computePrice,
|
|
1517
|
+
priorityFee
|
|
1518
|
+
};
|
|
1519
|
+
}
|
|
1520
|
+
/**
|
|
1521
|
+
* Record transaction result for learning
|
|
1522
|
+
*/
|
|
1523
|
+
recordResult(computeUsed, computeLimit, success, confirmationTimeMs) {
|
|
1524
|
+
this.history.push({
|
|
1525
|
+
computeUsed,
|
|
1526
|
+
computeLimit,
|
|
1527
|
+
success,
|
|
1528
|
+
confirmationTimeMs,
|
|
1529
|
+
timestamp: Date.now()
|
|
1530
|
+
});
|
|
1531
|
+
if (this.history.length > this.maxHistorySize) {
|
|
1532
|
+
this.history.shift();
|
|
1533
|
+
}
|
|
1534
|
+
const recent = this.history.slice(-20);
|
|
1535
|
+
const successes = recent.filter((h) => h.success).length;
|
|
1536
|
+
this.networkStats.recentSuccessRate = successes / recent.length;
|
|
1537
|
+
}
|
|
1538
|
+
/**
|
|
1539
|
+
* Get recommended compute limit based on history
|
|
1540
|
+
*/
|
|
1541
|
+
getRecommendedComputeLimit() {
|
|
1542
|
+
if (this.history.length === 0) {
|
|
1543
|
+
return this.baseConfig.computeUnitLimit;
|
|
1544
|
+
}
|
|
1545
|
+
const computeUsed = this.history.map((h) => h.computeUsed).sort((a, b) => a - b);
|
|
1546
|
+
const p95Index = Math.floor(computeUsed.length * 0.95);
|
|
1547
|
+
const p95Compute = computeUsed[p95Index] ?? computeUsed[computeUsed.length - 1] ?? this.baseConfig.computeUnitLimit;
|
|
1548
|
+
return Math.ceil(p95Compute * 1.2);
|
|
1549
|
+
}
|
|
1550
|
+
/**
|
|
1551
|
+
* Get optimization statistics
|
|
1552
|
+
*/
|
|
1553
|
+
getStats() {
|
|
1554
|
+
if (this.history.length === 0) {
|
|
1555
|
+
return {
|
|
1556
|
+
totalComputeUsed: 0,
|
|
1557
|
+
totalComputeLimit: 0,
|
|
1558
|
+
averageComputePerInstruction: 0,
|
|
1559
|
+
estimatedFee: 0,
|
|
1560
|
+
efficiency: 0
|
|
1561
|
+
};
|
|
1562
|
+
}
|
|
1563
|
+
const totalUsed = this.history.reduce((sum, h) => sum + h.computeUsed, 0);
|
|
1564
|
+
const totalLimit = this.history.reduce((sum, h) => sum + h.computeLimit, 0);
|
|
1565
|
+
return {
|
|
1566
|
+
totalComputeUsed: totalUsed,
|
|
1567
|
+
totalComputeLimit: totalLimit,
|
|
1568
|
+
averageComputePerInstruction: totalUsed / this.history.length,
|
|
1569
|
+
estimatedFee: this.calculateEstimatedFee(),
|
|
1570
|
+
efficiency: totalLimit > 0 ? totalUsed / totalLimit : 0
|
|
1571
|
+
};
|
|
1572
|
+
}
|
|
1573
|
+
/**
|
|
1574
|
+
* Reset history
|
|
1575
|
+
*/
|
|
1576
|
+
reset() {
|
|
1577
|
+
this.history = [];
|
|
1578
|
+
this.networkStats = {
|
|
1579
|
+
averageComputePrice: 0,
|
|
1580
|
+
congestionLevel: 0,
|
|
1581
|
+
recentSuccessRate: 1
|
|
1582
|
+
};
|
|
1583
|
+
}
|
|
1584
|
+
calculateEstimatedFee() {
|
|
1585
|
+
const recent = this.history.slice(-10);
|
|
1586
|
+
if (recent.length === 0) return 0;
|
|
1587
|
+
const avgCompute = recent.reduce((sum, h) => sum + h.computeUsed, 0) / recent.length;
|
|
1588
|
+
return avgCompute * this.baseConfig.computeUnitPrice;
|
|
1589
|
+
}
|
|
1590
|
+
};
|
|
1591
|
+
var InstructionBatcher = class {
|
|
1592
|
+
groups = [];
|
|
1593
|
+
maxComputePerGroup = 12e5;
|
|
1594
|
+
// 1.2M compute units
|
|
1595
|
+
/**
|
|
1596
|
+
* Add an instruction group
|
|
1597
|
+
*/
|
|
1598
|
+
addGroup(group) {
|
|
1599
|
+
this.groups.push(group);
|
|
1600
|
+
return this;
|
|
1601
|
+
}
|
|
1602
|
+
/**
|
|
1603
|
+
* Batch all groups into optimal transaction sets
|
|
1604
|
+
*/
|
|
1605
|
+
batch() {
|
|
1606
|
+
const batches = [];
|
|
1607
|
+
let currentBatch = [];
|
|
1608
|
+
let currentCompute = 0;
|
|
1609
|
+
const sorted = [...this.groups].sort((a, b) => b.priority - a.priority);
|
|
1610
|
+
for (const group of sorted) {
|
|
1611
|
+
if (currentCompute + group.computeEstimate > this.maxComputePerGroup) {
|
|
1612
|
+
if (currentBatch.length > 0) {
|
|
1613
|
+
batches.push(currentBatch);
|
|
1614
|
+
}
|
|
1615
|
+
currentBatch = [group];
|
|
1616
|
+
currentCompute = group.computeEstimate;
|
|
1617
|
+
} else {
|
|
1618
|
+
currentBatch.push(group);
|
|
1619
|
+
currentCompute += group.computeEstimate;
|
|
1620
|
+
}
|
|
1621
|
+
}
|
|
1622
|
+
if (currentBatch.length > 0) {
|
|
1623
|
+
batches.push(currentBatch);
|
|
1624
|
+
}
|
|
1625
|
+
return batches;
|
|
1626
|
+
}
|
|
1627
|
+
/**
|
|
1628
|
+
* Set maximum compute per batch
|
|
1629
|
+
*/
|
|
1630
|
+
setMaxComputePerGroup(compute) {
|
|
1631
|
+
this.maxComputePerGroup = compute;
|
|
1632
|
+
return this;
|
|
1633
|
+
}
|
|
1634
|
+
/**
|
|
1635
|
+
* Clear all groups
|
|
1636
|
+
*/
|
|
1637
|
+
clear() {
|
|
1638
|
+
this.groups = [];
|
|
1639
|
+
return this;
|
|
1640
|
+
}
|
|
1641
|
+
};
|
|
1642
|
+
var TransactionOptimizer = class {
|
|
1643
|
+
config;
|
|
1644
|
+
budgetOptimizer;
|
|
1645
|
+
constructor(config = defaultTransactionConfig()) {
|
|
1646
|
+
this.config = config;
|
|
1647
|
+
this.budgetOptimizer = new ComputeBudgetOptimizer(config);
|
|
1648
|
+
}
|
|
1649
|
+
/**
|
|
1650
|
+
* Optimize a set of instructions
|
|
1651
|
+
*/
|
|
1652
|
+
optimize(instructions, options = {}) {
|
|
1653
|
+
const builder = new TransactionBuilder(this.config);
|
|
1654
|
+
builder.addInstructions(instructions);
|
|
1655
|
+
const result = builder.build();
|
|
1656
|
+
if (options.priority) {
|
|
1657
|
+
const budget = this.budgetOptimizer.getOptimizedBudget(options.priority);
|
|
1658
|
+
result.computeLimit = budget.computeLimit;
|
|
1659
|
+
result.computePrice = budget.computePrice;
|
|
1660
|
+
}
|
|
1661
|
+
return result;
|
|
1662
|
+
}
|
|
1663
|
+
/**
|
|
1664
|
+
* Optimize for minimum latency
|
|
1665
|
+
*/
|
|
1666
|
+
optimizeForLatency(instructions) {
|
|
1667
|
+
return this.optimize(instructions, { priority: "critical" });
|
|
1668
|
+
}
|
|
1669
|
+
/**
|
|
1670
|
+
* Optimize for minimum cost
|
|
1671
|
+
*/
|
|
1672
|
+
optimizeForCost(instructions) {
|
|
1673
|
+
return this.optimize(instructions, { priority: "low" });
|
|
1674
|
+
}
|
|
1675
|
+
/**
|
|
1676
|
+
* Get the compute budget optimizer
|
|
1677
|
+
*/
|
|
1678
|
+
getBudgetOptimizer() {
|
|
1679
|
+
return this.budgetOptimizer;
|
|
1680
|
+
}
|
|
1681
|
+
/**
|
|
1682
|
+
* Update configuration
|
|
1683
|
+
*/
|
|
1684
|
+
updateConfig(config) {
|
|
1685
|
+
this.config = { ...this.config, ...config };
|
|
1686
|
+
this.budgetOptimizer = new ComputeBudgetOptimizer(this.config);
|
|
1687
|
+
}
|
|
1688
|
+
};
|
|
1689
|
+
function createTransactionBuilder(config) {
|
|
1690
|
+
const fullConfig = { ...defaultTransactionConfig(), ...config };
|
|
1691
|
+
return new TransactionBuilder(fullConfig);
|
|
1692
|
+
}
|
|
1693
|
+
function createComputeBudgetOptimizer(config) {
|
|
1694
|
+
const fullConfig = { ...defaultTransactionConfig(), ...config };
|
|
1695
|
+
return new ComputeBudgetOptimizer(fullConfig);
|
|
1696
|
+
}
|
|
1697
|
+
function createInstructionBatcher() {
|
|
1698
|
+
return new InstructionBatcher();
|
|
1699
|
+
}
|
|
1700
|
+
function createTransactionOptimizer(config) {
|
|
1701
|
+
const fullConfig = { ...defaultTransactionConfig(), ...config };
|
|
1702
|
+
return new TransactionOptimizer(fullConfig);
|
|
1703
|
+
}
|
|
1704
|
+
function estimateCompute(operation) {
|
|
1705
|
+
const estimates = {
|
|
1706
|
+
transfer: 450,
|
|
1707
|
+
createAccount: 2500,
|
|
1708
|
+
createATA: 3500,
|
|
1709
|
+
closeAccount: 2500,
|
|
1710
|
+
syncNative: 500,
|
|
1711
|
+
pumpFunBuy: 45e3,
|
|
1712
|
+
pumpFunSell: 4e4,
|
|
1713
|
+
pumpSwapBuy: 5e4,
|
|
1714
|
+
pumpSwapSell: 45e3,
|
|
1715
|
+
raydiumSwap: 55e3,
|
|
1716
|
+
meteoraSwap: 6e4
|
|
1717
|
+
};
|
|
1718
|
+
return estimates[operation] || 3e3;
|
|
1719
|
+
}
|
|
1720
|
+
function calculateOptimalPrice(targetLatencyMs, currentCongestion) {
|
|
1721
|
+
const basePrice = 1e5;
|
|
1722
|
+
const latencyMultiplier = Math.max(1, 100 / targetLatencyMs);
|
|
1723
|
+
const congestionMultiplier = 1 + currentCongestion;
|
|
1724
|
+
return Math.floor(basePrice * latencyMultiplier * congestionMultiplier);
|
|
1725
|
+
}
|
|
1726
|
+
|
|
1727
|
+
// src/perf/realtime.ts
|
|
1728
|
+
var ThreadPriorityLevel = /* @__PURE__ */ ((ThreadPriorityLevel2) => {
|
|
1729
|
+
ThreadPriorityLevel2[ThreadPriorityLevel2["Idle"] = 0] = "Idle";
|
|
1730
|
+
ThreadPriorityLevel2[ThreadPriorityLevel2["Lowest"] = 1] = "Lowest";
|
|
1731
|
+
ThreadPriorityLevel2[ThreadPriorityLevel2["Low"] = 2] = "Low";
|
|
1732
|
+
ThreadPriorityLevel2[ThreadPriorityLevel2["Normal"] = 3] = "Normal";
|
|
1733
|
+
ThreadPriorityLevel2[ThreadPriorityLevel2["High"] = 4] = "High";
|
|
1734
|
+
ThreadPriorityLevel2[ThreadPriorityLevel2["Highest"] = 5] = "Highest";
|
|
1735
|
+
ThreadPriorityLevel2[ThreadPriorityLevel2["Realtime"] = 6] = "Realtime";
|
|
1736
|
+
return ThreadPriorityLevel2;
|
|
1737
|
+
})(ThreadPriorityLevel || {});
|
|
1738
|
+
var SchedulerPolicy = /* @__PURE__ */ ((SchedulerPolicy2) => {
|
|
1739
|
+
SchedulerPolicy2["Normal"] = "normal";
|
|
1740
|
+
SchedulerPolicy2["FIFO"] = "fifo";
|
|
1741
|
+
SchedulerPolicy2["RoundRobin"] = "rr";
|
|
1742
|
+
SchedulerPolicy2["Batch"] = "batch";
|
|
1743
|
+
SchedulerPolicy2["Idle"] = "idle";
|
|
1744
|
+
return SchedulerPolicy2;
|
|
1745
|
+
})(SchedulerPolicy || {});
|
|
1746
|
+
function defaultRealtimeConfig() {
|
|
1747
|
+
return {
|
|
1748
|
+
enableRealtime: false,
|
|
1749
|
+
targetLatencyUs: 100,
|
|
1750
|
+
// 100 microseconds
|
|
1751
|
+
cpuCore: -1,
|
|
1752
|
+
// No pinning
|
|
1753
|
+
priority: 4 /* High */,
|
|
1754
|
+
busyWait: false,
|
|
1755
|
+
scheduler: "normal" /* Normal */,
|
|
1756
|
+
lockMemory: false
|
|
1757
|
+
};
|
|
1758
|
+
}
|
|
1759
|
+
var ThreadPriority = class {
|
|
1760
|
+
currentPriority = 3 /* Normal */;
|
|
1761
|
+
config;
|
|
1762
|
+
constructor(config = defaultRealtimeConfig()) {
|
|
1763
|
+
this.config = config;
|
|
1764
|
+
}
|
|
1765
|
+
/**
|
|
1766
|
+
* Set thread priority
|
|
1767
|
+
*/
|
|
1768
|
+
setPriority(priority) {
|
|
1769
|
+
this.currentPriority = priority;
|
|
1770
|
+
if (this.config.enableRealtime) {
|
|
1771
|
+
console.log(`Thread priority set to: ${ThreadPriorityLevel[priority]}`);
|
|
1772
|
+
}
|
|
1773
|
+
return true;
|
|
1774
|
+
}
|
|
1775
|
+
/**
|
|
1776
|
+
* Get current priority
|
|
1777
|
+
*/
|
|
1778
|
+
getPriority() {
|
|
1779
|
+
return this.currentPriority;
|
|
1780
|
+
}
|
|
1781
|
+
/**
|
|
1782
|
+
* Increase priority by one level
|
|
1783
|
+
*/
|
|
1784
|
+
increasePriority() {
|
|
1785
|
+
if (this.currentPriority < 6 /* Realtime */) {
|
|
1786
|
+
return this.setPriority(this.currentPriority + 1);
|
|
1787
|
+
}
|
|
1788
|
+
return false;
|
|
1789
|
+
}
|
|
1790
|
+
/**
|
|
1791
|
+
* Decrease priority by one level
|
|
1792
|
+
*/
|
|
1793
|
+
decreasePriority() {
|
|
1794
|
+
if (this.currentPriority > 0 /* Idle */) {
|
|
1795
|
+
return this.setPriority(this.currentPriority - 1);
|
|
1796
|
+
}
|
|
1797
|
+
return false;
|
|
1798
|
+
}
|
|
1799
|
+
/**
|
|
1800
|
+
* Set realtime priority
|
|
1801
|
+
*/
|
|
1802
|
+
setRealtime() {
|
|
1803
|
+
return this.setPriority(6 /* Realtime */);
|
|
1804
|
+
}
|
|
1805
|
+
/**
|
|
1806
|
+
* Set normal priority
|
|
1807
|
+
*/
|
|
1808
|
+
setNormal() {
|
|
1809
|
+
return this.setPriority(3 /* Normal */);
|
|
1810
|
+
}
|
|
1811
|
+
/**
|
|
1812
|
+
* Check if running at realtime priority
|
|
1813
|
+
*/
|
|
1814
|
+
isRealtime() {
|
|
1815
|
+
return this.currentPriority === 6 /* Realtime */;
|
|
1816
|
+
}
|
|
1817
|
+
};
|
|
1818
|
+
var RealtimeTuner = class {
|
|
1819
|
+
config;
|
|
1820
|
+
running = false;
|
|
1821
|
+
tunerInterval = null;
|
|
1822
|
+
latencies = [];
|
|
1823
|
+
stats;
|
|
1824
|
+
callbacks = [];
|
|
1825
|
+
lastAdjustment = 0;
|
|
1826
|
+
adjustmentCooldownMs = 1e3;
|
|
1827
|
+
constructor(config = defaultRealtimeConfig()) {
|
|
1828
|
+
this.config = config;
|
|
1829
|
+
this.stats = {
|
|
1830
|
+
adjustments: 0,
|
|
1831
|
+
averageLatencyUs: 0,
|
|
1832
|
+
minLatencyUs: Infinity,
|
|
1833
|
+
maxLatencyUs: 0,
|
|
1834
|
+
violations: 0,
|
|
1835
|
+
lastAdjustmentTime: 0
|
|
1836
|
+
};
|
|
1837
|
+
}
|
|
1838
|
+
/**
|
|
1839
|
+
* Start the realtime tuner
|
|
1840
|
+
*/
|
|
1841
|
+
start() {
|
|
1842
|
+
if (this.running) return;
|
|
1843
|
+
this.running = true;
|
|
1844
|
+
this.applyConfiguration();
|
|
1845
|
+
this.tunerInterval = setInterval(() => {
|
|
1846
|
+
this.tune();
|
|
1847
|
+
}, 100);
|
|
1848
|
+
console.log("Realtime tuner started");
|
|
1849
|
+
}
|
|
1850
|
+
/**
|
|
1851
|
+
* Stop the realtime tuner
|
|
1852
|
+
*/
|
|
1853
|
+
stop() {
|
|
1854
|
+
this.running = false;
|
|
1855
|
+
if (this.tunerInterval) {
|
|
1856
|
+
clearInterval(this.tunerInterval);
|
|
1857
|
+
this.tunerInterval = null;
|
|
1858
|
+
}
|
|
1859
|
+
console.log("Realtime tuner stopped");
|
|
1860
|
+
}
|
|
1861
|
+
/**
|
|
1862
|
+
* Record a latency measurement
|
|
1863
|
+
*/
|
|
1864
|
+
recordLatency(latencyUs) {
|
|
1865
|
+
this.latencies.push(latencyUs);
|
|
1866
|
+
if (this.latencies.length > 1e3) {
|
|
1867
|
+
this.latencies.shift();
|
|
1868
|
+
}
|
|
1869
|
+
if (latencyUs > this.config.targetLatencyUs) {
|
|
1870
|
+
this.stats.violations++;
|
|
1871
|
+
}
|
|
1872
|
+
this.stats.minLatencyUs = Math.min(this.stats.minLatencyUs, latencyUs);
|
|
1873
|
+
this.stats.maxLatencyUs = Math.max(this.stats.maxLatencyUs, latencyUs);
|
|
1874
|
+
}
|
|
1875
|
+
/**
|
|
1876
|
+
* Get current tuning statistics
|
|
1877
|
+
*/
|
|
1878
|
+
getStats() {
|
|
1879
|
+
if (this.latencies.length > 0) {
|
|
1880
|
+
this.stats.averageLatencyUs = this.latencies.reduce((a, b) => a + b, 0) / this.latencies.length;
|
|
1881
|
+
}
|
|
1882
|
+
return { ...this.stats };
|
|
1883
|
+
}
|
|
1884
|
+
/**
|
|
1885
|
+
* Register a callback for tuning events
|
|
1886
|
+
*/
|
|
1887
|
+
onTune(callback) {
|
|
1888
|
+
this.callbacks.push(callback);
|
|
1889
|
+
}
|
|
1890
|
+
/**
|
|
1891
|
+
* Reset statistics
|
|
1892
|
+
*/
|
|
1893
|
+
resetStats() {
|
|
1894
|
+
this.latencies = [];
|
|
1895
|
+
this.stats = {
|
|
1896
|
+
adjustments: 0,
|
|
1897
|
+
averageLatencyUs: 0,
|
|
1898
|
+
minLatencyUs: Infinity,
|
|
1899
|
+
maxLatencyUs: 0,
|
|
1900
|
+
violations: 0,
|
|
1901
|
+
lastAdjustmentTime: 0
|
|
1902
|
+
};
|
|
1903
|
+
}
|
|
1904
|
+
applyConfiguration() {
|
|
1905
|
+
const priority = new ThreadPriority(this.config);
|
|
1906
|
+
priority.setPriority(this.config.priority);
|
|
1907
|
+
console.log("Realtime configuration applied:", {
|
|
1908
|
+
targetLatencyUs: this.config.targetLatencyUs,
|
|
1909
|
+
cpuCore: this.config.cpuCore,
|
|
1910
|
+
priority: ThreadPriorityLevel[this.config.priority],
|
|
1911
|
+
busyWait: this.config.busyWait
|
|
1912
|
+
});
|
|
1913
|
+
}
|
|
1914
|
+
tune() {
|
|
1915
|
+
if (!this.running) return;
|
|
1916
|
+
const now = Date.now();
|
|
1917
|
+
if (now - this.lastAdjustment < this.adjustmentCooldownMs) {
|
|
1918
|
+
return;
|
|
1919
|
+
}
|
|
1920
|
+
if (this.latencies.length === 0) return;
|
|
1921
|
+
const avgLatency = this.latencies.reduce((a, b) => a + b, 0) / this.latencies.length;
|
|
1922
|
+
this.stats.averageLatencyUs = avgLatency;
|
|
1923
|
+
const violationRate = this.stats.violations / this.latencies.length;
|
|
1924
|
+
if (violationRate > 0.1) {
|
|
1925
|
+
this.adjustForLowerLatency();
|
|
1926
|
+
this.stats.adjustments++;
|
|
1927
|
+
this.stats.lastAdjustmentTime = now;
|
|
1928
|
+
this.lastAdjustment = now;
|
|
1929
|
+
}
|
|
1930
|
+
for (const callback of this.callbacks) {
|
|
1931
|
+
try {
|
|
1932
|
+
callback(this.getStats());
|
|
1933
|
+
} catch (error) {
|
|
1934
|
+
console.error("Tuning callback error:", error);
|
|
1935
|
+
}
|
|
1936
|
+
}
|
|
1937
|
+
}
|
|
1938
|
+
adjustForLowerLatency() {
|
|
1939
|
+
console.log("Adjusting for lower latency...");
|
|
1940
|
+
}
|
|
1941
|
+
};
|
|
1942
|
+
function busyWait(microseconds) {
|
|
1943
|
+
const start = process.hrtime.bigint();
|
|
1944
|
+
const target = start + BigInt(microseconds) * BigInt(1e3);
|
|
1945
|
+
while (process.hrtime.bigint() < target) {
|
|
1946
|
+
}
|
|
1947
|
+
}
|
|
1948
|
+
function spinLock(condition, timeoutUs) {
|
|
1949
|
+
const start = process.hrtime.bigint();
|
|
1950
|
+
const timeoutNs = BigInt(timeoutUs) * BigInt(1e3);
|
|
1951
|
+
while (!condition()) {
|
|
1952
|
+
if (process.hrtime.bigint() - start > timeoutNs) {
|
|
1953
|
+
return false;
|
|
1954
|
+
}
|
|
1955
|
+
}
|
|
1956
|
+
return true;
|
|
1957
|
+
}
|
|
1958
|
+
var LatencyMonitor = class {
|
|
1959
|
+
measurements = [];
|
|
1960
|
+
maxMeasurements;
|
|
1961
|
+
histogram = /* @__PURE__ */ new Map();
|
|
1962
|
+
bucketSize;
|
|
1963
|
+
constructor(maxMeasurements = 1e4, bucketSize = 10) {
|
|
1964
|
+
this.maxMeasurements = maxMeasurements;
|
|
1965
|
+
this.bucketSize = bucketSize;
|
|
1966
|
+
}
|
|
1967
|
+
/**
|
|
1968
|
+
* Record a latency measurement
|
|
1969
|
+
*/
|
|
1970
|
+
record(latencyUs) {
|
|
1971
|
+
this.measurements.push(latencyUs);
|
|
1972
|
+
if (this.measurements.length > this.maxMeasurements) {
|
|
1973
|
+
this.measurements.shift();
|
|
1974
|
+
}
|
|
1975
|
+
const bucket = Math.floor(latencyUs / this.bucketSize) * this.bucketSize;
|
|
1976
|
+
const count = this.histogram.get(bucket) || 0;
|
|
1977
|
+
this.histogram.set(bucket, count + 1);
|
|
1978
|
+
}
|
|
1979
|
+
/**
|
|
1980
|
+
* Get percentile latency
|
|
1981
|
+
*/
|
|
1982
|
+
getPercentile(percentile) {
|
|
1983
|
+
if (this.measurements.length === 0) return 0;
|
|
1984
|
+
const sorted = [...this.measurements].sort((a, b) => a - b);
|
|
1985
|
+
const index = Math.floor(percentile / 100 * sorted.length);
|
|
1986
|
+
return sorted[Math.min(index, sorted.length - 1)] ?? 0;
|
|
1987
|
+
}
|
|
1988
|
+
/**
|
|
1989
|
+
* Get average latency
|
|
1990
|
+
*/
|
|
1991
|
+
getAverage() {
|
|
1992
|
+
if (this.measurements.length === 0) return 0;
|
|
1993
|
+
return this.measurements.reduce((a, b) => a + b, 0) / this.measurements.length;
|
|
1994
|
+
}
|
|
1995
|
+
/**
|
|
1996
|
+
* Get minimum latency
|
|
1997
|
+
*/
|
|
1998
|
+
getMin() {
|
|
1999
|
+
if (this.measurements.length === 0) return 0;
|
|
2000
|
+
return Math.min(...this.measurements);
|
|
2001
|
+
}
|
|
2002
|
+
/**
|
|
2003
|
+
* Get maximum latency
|
|
2004
|
+
*/
|
|
2005
|
+
getMax() {
|
|
2006
|
+
if (this.measurements.length === 0) return 0;
|
|
2007
|
+
return Math.max(...this.measurements);
|
|
2008
|
+
}
|
|
2009
|
+
/**
|
|
2010
|
+
* Get histogram
|
|
2011
|
+
*/
|
|
2012
|
+
getHistogram() {
|
|
2013
|
+
return new Map(this.histogram);
|
|
2014
|
+
}
|
|
2015
|
+
/**
|
|
2016
|
+
* Reset all measurements
|
|
2017
|
+
*/
|
|
2018
|
+
reset() {
|
|
2019
|
+
this.measurements = [];
|
|
2020
|
+
this.histogram.clear();
|
|
2021
|
+
}
|
|
2022
|
+
/**
|
|
2023
|
+
* Get summary statistics
|
|
2024
|
+
*/
|
|
2025
|
+
getSummary() {
|
|
2026
|
+
return {
|
|
2027
|
+
count: this.measurements.length,
|
|
2028
|
+
min: this.getMin(),
|
|
2029
|
+
max: this.getMax(),
|
|
2030
|
+
avg: this.getAverage(),
|
|
2031
|
+
p50: this.getPercentile(50),
|
|
2032
|
+
p95: this.getPercentile(95),
|
|
2033
|
+
p99: this.getPercentile(99),
|
|
2034
|
+
p999: this.getPercentile(99.9)
|
|
2035
|
+
};
|
|
2036
|
+
}
|
|
2037
|
+
};
|
|
2038
|
+
var PerformanceGovernor = class {
|
|
2039
|
+
targetThroughput = 0;
|
|
2040
|
+
currentThroughput = 0;
|
|
2041
|
+
adjustments = 0;
|
|
2042
|
+
/**
|
|
2043
|
+
* Set target throughput (operations per second)
|
|
2044
|
+
*/
|
|
2045
|
+
setTargetThroughput(opsPerSecond) {
|
|
2046
|
+
this.targetThroughput = opsPerSecond;
|
|
2047
|
+
}
|
|
2048
|
+
/**
|
|
2049
|
+
* Report actual throughput
|
|
2050
|
+
*/
|
|
2051
|
+
reportThroughput(opsPerSecond) {
|
|
2052
|
+
this.currentThroughput = opsPerSecond;
|
|
2053
|
+
}
|
|
2054
|
+
/**
|
|
2055
|
+
* Get recommended batch size
|
|
2056
|
+
*/
|
|
2057
|
+
getRecommendedBatchSize() {
|
|
2058
|
+
if (this.targetThroughput === 0) return 1;
|
|
2059
|
+
const ratio = this.currentThroughput / this.targetThroughput;
|
|
2060
|
+
if (ratio < 0.5) {
|
|
2061
|
+
return 1;
|
|
2062
|
+
} else if (ratio > 1.5) {
|
|
2063
|
+
return 10;
|
|
2064
|
+
}
|
|
2065
|
+
return 5;
|
|
2066
|
+
}
|
|
2067
|
+
/**
|
|
2068
|
+
* Get adjustment count
|
|
2069
|
+
*/
|
|
2070
|
+
getAdjustments() {
|
|
2071
|
+
return this.adjustments;
|
|
2072
|
+
}
|
|
2073
|
+
};
|
|
2074
|
+
function createRealtimeTuner(config) {
|
|
2075
|
+
const fullConfig = { ...defaultRealtimeConfig(), ...config };
|
|
2076
|
+
return new RealtimeTuner(fullConfig);
|
|
2077
|
+
}
|
|
2078
|
+
function createThreadPriority(config) {
|
|
2079
|
+
const fullConfig = { ...defaultRealtimeConfig(), ...config };
|
|
2080
|
+
return new ThreadPriority(fullConfig);
|
|
2081
|
+
}
|
|
2082
|
+
function createLatencyMonitor(maxMeasurements, bucketSize) {
|
|
2083
|
+
return new LatencyMonitor(maxMeasurements, bucketSize);
|
|
2084
|
+
}
|
|
2085
|
+
function createPerformanceGovernor() {
|
|
2086
|
+
return new PerformanceGovernor();
|
|
2087
|
+
}
|
|
2088
|
+
function measureTime(fn) {
|
|
2089
|
+
const start = process.hrtime.bigint();
|
|
2090
|
+
const result = fn();
|
|
2091
|
+
const elapsed = Number(process.hrtime.bigint() - start) / 1e3;
|
|
2092
|
+
return { result, elapsedUs: elapsed };
|
|
2093
|
+
}
|
|
2094
|
+
function createTimer() {
|
|
2095
|
+
let startTime = BigInt(0);
|
|
2096
|
+
return {
|
|
2097
|
+
start: () => {
|
|
2098
|
+
startTime = process.hrtime.bigint();
|
|
2099
|
+
},
|
|
2100
|
+
elapsed: () => {
|
|
2101
|
+
return Number(process.hrtime.bigint() - startTime) / 1e3;
|
|
2102
|
+
},
|
|
2103
|
+
reset: () => {
|
|
2104
|
+
startTime = process.hrtime.bigint();
|
|
2105
|
+
}
|
|
2106
|
+
};
|
|
2107
|
+
}
|
|
2108
|
+
|
|
2109
|
+
// src/perf/simd.ts
|
|
2110
|
+
function defaultSIMDConfig() {
|
|
2111
|
+
return {
|
|
2112
|
+
enableSIMD: true,
|
|
2113
|
+
preferredWidth: 128,
|
|
2114
|
+
enableWasmSIMD: true,
|
|
2115
|
+
fallbackToScalar: true
|
|
2116
|
+
};
|
|
2117
|
+
}
|
|
2118
|
+
var SIMDDetector = class {
|
|
2119
|
+
capabilities = null;
|
|
2120
|
+
/**
|
|
2121
|
+
* Detect SIMD capabilities
|
|
2122
|
+
*/
|
|
2123
|
+
detect() {
|
|
2124
|
+
if (this.capabilities) {
|
|
2125
|
+
return this.capabilities;
|
|
2126
|
+
}
|
|
2127
|
+
this.capabilities = {
|
|
2128
|
+
sse: false,
|
|
2129
|
+
sse2: false,
|
|
2130
|
+
sse3: false,
|
|
2131
|
+
ssse3: false,
|
|
2132
|
+
sse41: false,
|
|
2133
|
+
sse42: false,
|
|
2134
|
+
avx: false,
|
|
2135
|
+
avx2: false,
|
|
2136
|
+
avx512: false,
|
|
2137
|
+
neon: this.detectNEON(),
|
|
2138
|
+
wasmSimd128: this.detectWasmSIMD128()
|
|
2139
|
+
};
|
|
2140
|
+
return this.capabilities;
|
|
2141
|
+
}
|
|
2142
|
+
/**
|
|
2143
|
+
* Check if WebAssembly SIMD128 is available
|
|
2144
|
+
*/
|
|
2145
|
+
detectWasmSIMD128() {
|
|
2146
|
+
if (typeof WebAssembly === "undefined") {
|
|
2147
|
+
return false;
|
|
2148
|
+
}
|
|
2149
|
+
try {
|
|
2150
|
+
const simdTest = new Uint8Array([
|
|
2151
|
+
0,
|
|
2152
|
+
97,
|
|
2153
|
+
115,
|
|
2154
|
+
109,
|
|
2155
|
+
// WASM magic
|
|
2156
|
+
1,
|
|
2157
|
+
0,
|
|
2158
|
+
0,
|
|
2159
|
+
0,
|
|
2160
|
+
// version
|
|
2161
|
+
1,
|
|
2162
|
+
5,
|
|
2163
|
+
1,
|
|
2164
|
+
// type section
|
|
2165
|
+
96,
|
|
2166
|
+
0,
|
|
2167
|
+
1,
|
|
2168
|
+
123,
|
|
2169
|
+
// func type with v128 return
|
|
2170
|
+
3,
|
|
2171
|
+
2,
|
|
2172
|
+
1,
|
|
2173
|
+
0,
|
|
2174
|
+
// func section
|
|
2175
|
+
10,
|
|
2176
|
+
11,
|
|
2177
|
+
1,
|
|
2178
|
+
// code section
|
|
2179
|
+
9,
|
|
2180
|
+
0,
|
|
2181
|
+
// func body
|
|
2182
|
+
253,
|
|
2183
|
+
15,
|
|
2184
|
+
0,
|
|
2185
|
+
0,
|
|
2186
|
+
// v128.const
|
|
2187
|
+
0,
|
|
2188
|
+
0,
|
|
2189
|
+
0,
|
|
2190
|
+
0,
|
|
2191
|
+
0,
|
|
2192
|
+
0,
|
|
2193
|
+
0,
|
|
2194
|
+
0,
|
|
2195
|
+
11
|
|
2196
|
+
// end
|
|
2197
|
+
]);
|
|
2198
|
+
WebAssembly.compile(simdTest);
|
|
2199
|
+
return true;
|
|
2200
|
+
} catch {
|
|
2201
|
+
return false;
|
|
2202
|
+
}
|
|
2203
|
+
}
|
|
2204
|
+
/**
|
|
2205
|
+
* Detect NEON support (ARM)
|
|
2206
|
+
*/
|
|
2207
|
+
detectNEON() {
|
|
2208
|
+
if (typeof process !== "undefined" && process.arch === "arm64") {
|
|
2209
|
+
return true;
|
|
2210
|
+
}
|
|
2211
|
+
return false;
|
|
2212
|
+
}
|
|
2213
|
+
/**
|
|
2214
|
+
* Check if specific capability is available
|
|
2215
|
+
*/
|
|
2216
|
+
hasCapability(capability) {
|
|
2217
|
+
const caps = this.detect();
|
|
2218
|
+
return caps[capability];
|
|
2219
|
+
}
|
|
2220
|
+
/**
|
|
2221
|
+
* Get optimal vector width
|
|
2222
|
+
*/
|
|
2223
|
+
getOptimalWidth() {
|
|
2224
|
+
const caps = this.detect();
|
|
2225
|
+
if (caps.avx512) return 512;
|
|
2226
|
+
if (caps.avx || caps.avx2) return 256;
|
|
2227
|
+
if (caps.sse || caps.sse2 || caps.neon || caps.wasmSimd128) return 128;
|
|
2228
|
+
return 64;
|
|
2229
|
+
}
|
|
2230
|
+
/**
|
|
2231
|
+
* Check if any SIMD is available
|
|
2232
|
+
*/
|
|
2233
|
+
hasAnySIMD() {
|
|
2234
|
+
const caps = this.detect();
|
|
2235
|
+
return Object.values(caps).some((v) => v);
|
|
2236
|
+
}
|
|
2237
|
+
};
|
|
2238
|
+
var VectorizedMath = class {
|
|
2239
|
+
config;
|
|
2240
|
+
detector;
|
|
2241
|
+
constructor(config = defaultSIMDConfig()) {
|
|
2242
|
+
this.config = config;
|
|
2243
|
+
this.detector = new SIMDDetector();
|
|
2244
|
+
}
|
|
2245
|
+
/**
|
|
2246
|
+
* Vector addition: result = a + b
|
|
2247
|
+
*/
|
|
2248
|
+
add(a, b, result) {
|
|
2249
|
+
const len = Math.min(a.length, b.length);
|
|
2250
|
+
const out = result || new Float32Array(len);
|
|
2251
|
+
if (this.config.enableSIMD && this.detector.hasAnySIMD()) {
|
|
2252
|
+
const simdLen = len - len % 4;
|
|
2253
|
+
for (let i = 0; i < simdLen; i += 4) {
|
|
2254
|
+
out[i] = a[i] + b[i];
|
|
2255
|
+
out[i + 1] = a[i + 1] + b[i + 1];
|
|
2256
|
+
out[i + 2] = a[i + 2] + b[i + 2];
|
|
2257
|
+
out[i + 3] = a[i + 3] + b[i + 3];
|
|
2258
|
+
}
|
|
2259
|
+
for (let i = simdLen; i < len; i++) {
|
|
2260
|
+
out[i] = a[i] + b[i];
|
|
2261
|
+
}
|
|
2262
|
+
} else {
|
|
2263
|
+
for (let i = 0; i < len; i++) {
|
|
2264
|
+
out[i] = a[i] + b[i];
|
|
2265
|
+
}
|
|
2266
|
+
}
|
|
2267
|
+
return out;
|
|
2268
|
+
}
|
|
2269
|
+
/**
|
|
2270
|
+
* Vector subtraction: result = a - b
|
|
2271
|
+
*/
|
|
2272
|
+
subtract(a, b, result) {
|
|
2273
|
+
const len = Math.min(a.length, b.length);
|
|
2274
|
+
const out = result || new Float32Array(len);
|
|
2275
|
+
if (this.config.enableSIMD && this.detector.hasAnySIMD()) {
|
|
2276
|
+
const simdLen = len - len % 4;
|
|
2277
|
+
for (let i = 0; i < simdLen; i += 4) {
|
|
2278
|
+
out[i] = a[i] - b[i];
|
|
2279
|
+
out[i + 1] = a[i + 1] - b[i + 1];
|
|
2280
|
+
out[i + 2] = a[i + 2] - b[i + 2];
|
|
2281
|
+
out[i + 3] = a[i + 3] - b[i + 3];
|
|
2282
|
+
}
|
|
2283
|
+
for (let i = simdLen; i < len; i++) {
|
|
2284
|
+
out[i] = a[i] - b[i];
|
|
2285
|
+
}
|
|
2286
|
+
} else {
|
|
2287
|
+
for (let i = 0; i < len; i++) {
|
|
2288
|
+
out[i] = a[i] - b[i];
|
|
2289
|
+
}
|
|
2290
|
+
}
|
|
2291
|
+
return out;
|
|
2292
|
+
}
|
|
2293
|
+
/**
|
|
2294
|
+
* Vector multiplication: result = a * b
|
|
2295
|
+
*/
|
|
2296
|
+
multiply(a, b, result) {
|
|
2297
|
+
const len = Math.min(a.length, b.length);
|
|
2298
|
+
const out = result || new Float32Array(len);
|
|
2299
|
+
if (this.config.enableSIMD && this.detector.hasAnySIMD()) {
|
|
2300
|
+
const simdLen = len - len % 4;
|
|
2301
|
+
for (let i = 0; i < simdLen; i += 4) {
|
|
2302
|
+
out[i] = a[i] * b[i];
|
|
2303
|
+
out[i + 1] = a[i + 1] * b[i + 1];
|
|
2304
|
+
out[i + 2] = a[i + 2] * b[i + 2];
|
|
2305
|
+
out[i + 3] = a[i + 3] * b[i + 3];
|
|
2306
|
+
}
|
|
2307
|
+
for (let i = simdLen; i < len; i++) {
|
|
2308
|
+
out[i] = a[i] * b[i];
|
|
2309
|
+
}
|
|
2310
|
+
} else {
|
|
2311
|
+
for (let i = 0; i < len; i++) {
|
|
2312
|
+
out[i] = a[i] * b[i];
|
|
2313
|
+
}
|
|
2314
|
+
}
|
|
2315
|
+
return out;
|
|
2316
|
+
}
|
|
2317
|
+
/**
|
|
2318
|
+
* Vector division: result = a / b
|
|
2319
|
+
*/
|
|
2320
|
+
divide(a, b, result) {
|
|
2321
|
+
const len = Math.min(a.length, b.length);
|
|
2322
|
+
const out = result || new Float32Array(len);
|
|
2323
|
+
if (this.config.enableSIMD && this.detector.hasAnySIMD()) {
|
|
2324
|
+
const simdLen = len - len % 4;
|
|
2325
|
+
for (let i = 0; i < simdLen; i += 4) {
|
|
2326
|
+
out[i] = a[i] / b[i];
|
|
2327
|
+
out[i + 1] = a[i + 1] / b[i + 1];
|
|
2328
|
+
out[i + 2] = a[i + 2] / b[i + 2];
|
|
2329
|
+
out[i + 3] = a[i + 3] / b[i + 3];
|
|
2330
|
+
}
|
|
2331
|
+
for (let i = simdLen; i < len; i++) {
|
|
2332
|
+
out[i] = a[i] / b[i];
|
|
2333
|
+
}
|
|
2334
|
+
} else {
|
|
2335
|
+
for (let i = 0; i < len; i++) {
|
|
2336
|
+
out[i] = a[i] / b[i];
|
|
2337
|
+
}
|
|
2338
|
+
}
|
|
2339
|
+
return out;
|
|
2340
|
+
}
|
|
2341
|
+
/**
|
|
2342
|
+
* Vector dot product
|
|
2343
|
+
*/
|
|
2344
|
+
dot(a, b) {
|
|
2345
|
+
const len = Math.min(a.length, b.length);
|
|
2346
|
+
let sum = 0;
|
|
2347
|
+
if (this.config.enableSIMD && this.detector.hasAnySIMD()) {
|
|
2348
|
+
const simdLen = len - len % 4;
|
|
2349
|
+
let sum0 = 0, sum1 = 0, sum2 = 0, sum3 = 0;
|
|
2350
|
+
for (let i = 0; i < simdLen; i += 4) {
|
|
2351
|
+
sum0 += a[i] * b[i];
|
|
2352
|
+
sum1 += a[i + 1] * b[i + 1];
|
|
2353
|
+
sum2 += a[i + 2] * b[i + 2];
|
|
2354
|
+
sum3 += a[i + 3] * b[i + 3];
|
|
2355
|
+
}
|
|
2356
|
+
sum = sum0 + sum1 + sum2 + sum3;
|
|
2357
|
+
for (let i = simdLen; i < len; i++) {
|
|
2358
|
+
sum += a[i] * b[i];
|
|
2359
|
+
}
|
|
2360
|
+
} else {
|
|
2361
|
+
for (let i = 0; i < len; i++) {
|
|
2362
|
+
sum += a[i] * b[i];
|
|
2363
|
+
}
|
|
2364
|
+
}
|
|
2365
|
+
return sum;
|
|
2366
|
+
}
|
|
2367
|
+
/**
|
|
2368
|
+
* Vector sum
|
|
2369
|
+
*/
|
|
2370
|
+
sum(a) {
|
|
2371
|
+
let sum = 0;
|
|
2372
|
+
if (this.config.enableSIMD && this.detector.hasAnySIMD()) {
|
|
2373
|
+
const len = a.length;
|
|
2374
|
+
const simdLen = len - len % 4;
|
|
2375
|
+
let sum0 = 0, sum1 = 0, sum2 = 0, sum3 = 0;
|
|
2376
|
+
for (let i = 0; i < simdLen; i += 4) {
|
|
2377
|
+
sum0 += a[i];
|
|
2378
|
+
sum1 += a[i + 1];
|
|
2379
|
+
sum2 += a[i + 2];
|
|
2380
|
+
sum3 += a[i + 3];
|
|
2381
|
+
}
|
|
2382
|
+
sum = sum0 + sum1 + sum2 + sum3;
|
|
2383
|
+
for (let i = simdLen; i < len; i++) {
|
|
2384
|
+
sum += a[i];
|
|
2385
|
+
}
|
|
2386
|
+
} else {
|
|
2387
|
+
for (let i = 0; i < a.length; i++) {
|
|
2388
|
+
sum += a[i];
|
|
2389
|
+
}
|
|
2390
|
+
}
|
|
2391
|
+
return sum;
|
|
2392
|
+
}
|
|
2393
|
+
/**
|
|
2394
|
+
* Vector minimum
|
|
2395
|
+
*/
|
|
2396
|
+
min(a) {
|
|
2397
|
+
if (a.length === 0) return NaN;
|
|
2398
|
+
let min = a[0];
|
|
2399
|
+
for (let i = 1; i < a.length; i++) {
|
|
2400
|
+
if (a[i] < min) min = a[i];
|
|
2401
|
+
}
|
|
2402
|
+
return min;
|
|
2403
|
+
}
|
|
2404
|
+
/**
|
|
2405
|
+
* Vector maximum
|
|
2406
|
+
*/
|
|
2407
|
+
max(a) {
|
|
2408
|
+
if (a.length === 0) return NaN;
|
|
2409
|
+
let max = a[0];
|
|
2410
|
+
for (let i = 1; i < a.length; i++) {
|
|
2411
|
+
if (a[i] > max) max = a[i];
|
|
2412
|
+
}
|
|
2413
|
+
return max;
|
|
2414
|
+
}
|
|
2415
|
+
/**
|
|
2416
|
+
* Element-wise absolute value
|
|
2417
|
+
*/
|
|
2418
|
+
abs(a, result) {
|
|
2419
|
+
const out = result || new Float32Array(a.length);
|
|
2420
|
+
for (let i = 0; i < a.length; i++) {
|
|
2421
|
+
out[i] = Math.abs(a[i]);
|
|
2422
|
+
}
|
|
2423
|
+
return out;
|
|
2424
|
+
}
|
|
2425
|
+
/**
|
|
2426
|
+
* Element-wise square root
|
|
2427
|
+
*/
|
|
2428
|
+
sqrt(a, result) {
|
|
2429
|
+
const out = result || new Float32Array(a.length);
|
|
2430
|
+
for (let i = 0; i < a.length; i++) {
|
|
2431
|
+
out[i] = Math.sqrt(a[i]);
|
|
2432
|
+
}
|
|
2433
|
+
return out;
|
|
2434
|
+
}
|
|
2435
|
+
};
|
|
2436
|
+
var CryptoSIMD = class {
|
|
2437
|
+
config;
|
|
2438
|
+
detector;
|
|
2439
|
+
constructor(config = defaultSIMDConfig()) {
|
|
2440
|
+
this.config = config;
|
|
2441
|
+
this.detector = new SIMDDetector();
|
|
2442
|
+
}
|
|
2443
|
+
/**
|
|
2444
|
+
* XOR two byte arrays (SIMD-accelerated)
|
|
2445
|
+
*/
|
|
2446
|
+
xor(a, b, result) {
|
|
2447
|
+
const len = Math.min(a.length, b.length);
|
|
2448
|
+
const out = result || new Uint8Array(len);
|
|
2449
|
+
if (this.config.enableSIMD && this.detector.hasAnySIMD()) {
|
|
2450
|
+
const simdLen = len - len % 16;
|
|
2451
|
+
for (let i = 0; i < simdLen; i += 16) {
|
|
2452
|
+
for (let j = 0; j < 16; j++) {
|
|
2453
|
+
out[i + j] = a[i + j] ^ b[i + j];
|
|
2454
|
+
}
|
|
2455
|
+
}
|
|
2456
|
+
for (let i = simdLen; i < len; i++) {
|
|
2457
|
+
out[i] = a[i] ^ b[i];
|
|
2458
|
+
}
|
|
2459
|
+
} else {
|
|
2460
|
+
for (let i = 0; i < len; i++) {
|
|
2461
|
+
out[i] = a[i] ^ b[i];
|
|
2462
|
+
}
|
|
2463
|
+
}
|
|
2464
|
+
return out;
|
|
2465
|
+
}
|
|
2466
|
+
/**
|
|
2467
|
+
* Compare two byte arrays for equality (SIMD-accelerated)
|
|
2468
|
+
*/
|
|
2469
|
+
equals(a, b) {
|
|
2470
|
+
if (a.length !== b.length) return false;
|
|
2471
|
+
if (this.config.enableSIMD && this.detector.hasAnySIMD()) {
|
|
2472
|
+
const len = a.length;
|
|
2473
|
+
const simdLen = len - len % 16;
|
|
2474
|
+
for (let i = 0; i < simdLen; i += 16) {
|
|
2475
|
+
for (let j = 0; j < 16; j++) {
|
|
2476
|
+
if (a[i + j] !== b[i + j]) return false;
|
|
2477
|
+
}
|
|
2478
|
+
}
|
|
2479
|
+
for (let i = simdLen; i < len; i++) {
|
|
2480
|
+
if (a[i] !== b[i]) return false;
|
|
2481
|
+
}
|
|
2482
|
+
} else {
|
|
2483
|
+
for (let i = 0; i < a.length; i++) {
|
|
2484
|
+
if (a[i] !== b[i]) return false;
|
|
2485
|
+
}
|
|
2486
|
+
}
|
|
2487
|
+
return true;
|
|
2488
|
+
}
|
|
2489
|
+
/**
|
|
2490
|
+
* Fill array with value (SIMD-accelerated)
|
|
2491
|
+
*/
|
|
2492
|
+
fill(buffer, value) {
|
|
2493
|
+
if (this.config.enableSIMD && this.detector.hasAnySIMD()) {
|
|
2494
|
+
const len = buffer.length;
|
|
2495
|
+
const simdLen = len - len % 16;
|
|
2496
|
+
for (let i = 0; i < simdLen; i += 16) {
|
|
2497
|
+
for (let j = 0; j < 16; j++) {
|
|
2498
|
+
buffer[i + j] = value;
|
|
2499
|
+
}
|
|
2500
|
+
}
|
|
2501
|
+
for (let i = simdLen; i < len; i++) {
|
|
2502
|
+
buffer[i] = value;
|
|
2503
|
+
}
|
|
2504
|
+
} else {
|
|
2505
|
+
buffer.fill(value);
|
|
2506
|
+
}
|
|
2507
|
+
}
|
|
2508
|
+
/**
|
|
2509
|
+
* Copy bytes (SIMD-accelerated)
|
|
2510
|
+
*/
|
|
2511
|
+
copy(src, dst, srcOffset = 0, dstOffset = 0, length) {
|
|
2512
|
+
const len = length || Math.min(src.length - srcOffset, dst.length - dstOffset);
|
|
2513
|
+
if (this.config.enableSIMD && this.detector.hasAnySIMD()) {
|
|
2514
|
+
const simdLen = len - len % 16;
|
|
2515
|
+
for (let i = 0; i < simdLen; i += 16) {
|
|
2516
|
+
for (let j = 0; j < 16; j++) {
|
|
2517
|
+
dst[dstOffset + i + j] = src[srcOffset + i + j];
|
|
2518
|
+
}
|
|
2519
|
+
}
|
|
2520
|
+
for (let i = simdLen; i < len; i++) {
|
|
2521
|
+
dst[dstOffset + i] = src[srcOffset + i];
|
|
2522
|
+
}
|
|
2523
|
+
} else {
|
|
2524
|
+
dst.set(src.subarray(srcOffset, srcOffset + len), dstOffset);
|
|
2525
|
+
}
|
|
2526
|
+
}
|
|
2527
|
+
/**
|
|
2528
|
+
* Compute parity of byte array
|
|
2529
|
+
*/
|
|
2530
|
+
parity(data) {
|
|
2531
|
+
let parity = 0;
|
|
2532
|
+
for (let i = 0; i < data.length; i++) {
|
|
2533
|
+
parity ^= data[i];
|
|
2534
|
+
}
|
|
2535
|
+
return parity;
|
|
2536
|
+
}
|
|
2537
|
+
/**
|
|
2538
|
+
* Rotate bytes left
|
|
2539
|
+
*/
|
|
2540
|
+
rotateLeft(data, bits, result) {
|
|
2541
|
+
const out = result || new Uint8Array(data.length);
|
|
2542
|
+
const bytes = Math.floor(bits / 8);
|
|
2543
|
+
const remainingBits = bits % 8;
|
|
2544
|
+
if (remainingBits === 0) {
|
|
2545
|
+
for (let i = 0; i < data.length; i++) {
|
|
2546
|
+
out[i] = data[(i + bytes) % data.length];
|
|
2547
|
+
}
|
|
2548
|
+
} else {
|
|
2549
|
+
for (let i = 0; i < data.length; i++) {
|
|
2550
|
+
const srcIdx = (i + bytes) % data.length;
|
|
2551
|
+
const nextIdx = (srcIdx + 1) % data.length;
|
|
2552
|
+
out[i] = data[srcIdx] << remainingBits | data[nextIdx] >> 8 - remainingBits;
|
|
2553
|
+
}
|
|
2554
|
+
}
|
|
2555
|
+
return out;
|
|
2556
|
+
}
|
|
2557
|
+
};
|
|
2558
|
+
var Float32x4 = class _Float32x4 {
|
|
2559
|
+
data;
|
|
2560
|
+
constructor(x, y, z, w) {
|
|
2561
|
+
this.data = new Float32Array(4);
|
|
2562
|
+
if (x !== void 0) this.data[0] = x;
|
|
2563
|
+
if (y !== void 0) this.data[1] = y;
|
|
2564
|
+
if (z !== void 0) this.data[2] = z;
|
|
2565
|
+
if (w !== void 0) this.data[3] = w;
|
|
2566
|
+
}
|
|
2567
|
+
static fromArray(arr, offset = 0) {
|
|
2568
|
+
return new _Float32x4(arr[offset], arr[offset + 1], arr[offset + 2], arr[offset + 3]);
|
|
2569
|
+
}
|
|
2570
|
+
add(other) {
|
|
2571
|
+
return new _Float32x4(
|
|
2572
|
+
this.data[0] + other.data[0],
|
|
2573
|
+
this.data[1] + other.data[1],
|
|
2574
|
+
this.data[2] + other.data[2],
|
|
2575
|
+
this.data[3] + other.data[3]
|
|
2576
|
+
);
|
|
2577
|
+
}
|
|
2578
|
+
subtract(other) {
|
|
2579
|
+
return new _Float32x4(
|
|
2580
|
+
this.data[0] - other.data[0],
|
|
2581
|
+
this.data[1] - other.data[1],
|
|
2582
|
+
this.data[2] - other.data[2],
|
|
2583
|
+
this.data[3] - other.data[3]
|
|
2584
|
+
);
|
|
2585
|
+
}
|
|
2586
|
+
multiply(other) {
|
|
2587
|
+
return new _Float32x4(
|
|
2588
|
+
this.data[0] * other.data[0],
|
|
2589
|
+
this.data[1] * other.data[1],
|
|
2590
|
+
this.data[2] * other.data[2],
|
|
2591
|
+
this.data[3] * other.data[3]
|
|
2592
|
+
);
|
|
2593
|
+
}
|
|
2594
|
+
toArray() {
|
|
2595
|
+
return this.data.slice();
|
|
2596
|
+
}
|
|
2597
|
+
get x() {
|
|
2598
|
+
return this.data[0];
|
|
2599
|
+
}
|
|
2600
|
+
get y() {
|
|
2601
|
+
return this.data[1];
|
|
2602
|
+
}
|
|
2603
|
+
get z() {
|
|
2604
|
+
return this.data[2];
|
|
2605
|
+
}
|
|
2606
|
+
get w() {
|
|
2607
|
+
return this.data[3];
|
|
2608
|
+
}
|
|
2609
|
+
};
|
|
2610
|
+
function createSIMDDetector() {
|
|
2611
|
+
return new SIMDDetector();
|
|
2612
|
+
}
|
|
2613
|
+
function createVectorizedMath(config) {
|
|
2614
|
+
const fullConfig = { ...defaultSIMDConfig(), ...config };
|
|
2615
|
+
return new VectorizedMath(fullConfig);
|
|
2616
|
+
}
|
|
2617
|
+
function createCryptoSIMD(config) {
|
|
2618
|
+
const fullConfig = { ...defaultSIMDConfig(), ...config };
|
|
2619
|
+
return new CryptoSIMD(fullConfig);
|
|
2620
|
+
}
|
|
2621
|
+
function isSIMDAvailable() {
|
|
2622
|
+
return new SIMDDetector().hasAnySIMD();
|
|
2623
|
+
}
|
|
2624
|
+
function getOptimalSIMDWidth() {
|
|
2625
|
+
return new SIMDDetector().getOptimalWidth();
|
|
2626
|
+
}
|
|
2627
|
+
|
|
2628
|
+
// src/perf/syscall-bypass.ts
|
|
2629
|
+
function defaultSyscallBypassConfig() {
|
|
2630
|
+
return {
|
|
2631
|
+
enableFastTime: true,
|
|
2632
|
+
timeCacheIntervalUs: 1e3,
|
|
2633
|
+
// 1ms
|
|
2634
|
+
enableBatching: true,
|
|
2635
|
+
maxBatchSize: 64,
|
|
2636
|
+
useVdsoTime: true
|
|
2637
|
+
};
|
|
2638
|
+
}
|
|
2639
|
+
var FastTimeProvider = class {
|
|
2640
|
+
cachedTimeNs = BigInt(0);
|
|
2641
|
+
cachedTimeMs = 0;
|
|
2642
|
+
lastUpdateNs = BigInt(0);
|
|
2643
|
+
updateIntervalNs;
|
|
2644
|
+
running = false;
|
|
2645
|
+
updateTimer = null;
|
|
2646
|
+
useHighRes;
|
|
2647
|
+
constructor(updateIntervalUs = 1e3, useHighRes = true) {
|
|
2648
|
+
this.updateIntervalNs = BigInt(updateIntervalUs * 1e3);
|
|
2649
|
+
this.useHighRes = useHighRes;
|
|
2650
|
+
this.updateTime();
|
|
2651
|
+
}
|
|
2652
|
+
/**
|
|
2653
|
+
* Start the background time update loop
|
|
2654
|
+
*/
|
|
2655
|
+
start() {
|
|
2656
|
+
if (this.running) return;
|
|
2657
|
+
this.running = true;
|
|
2658
|
+
const intervalMs = Number(this.updateIntervalNs) / 1e6;
|
|
2659
|
+
this.updateTimer = setInterval(() => {
|
|
2660
|
+
this.updateTime();
|
|
2661
|
+
}, Math.max(1, intervalMs));
|
|
2662
|
+
}
|
|
2663
|
+
/**
|
|
2664
|
+
* Stop the background time update loop
|
|
2665
|
+
*/
|
|
2666
|
+
stop() {
|
|
2667
|
+
this.running = false;
|
|
2668
|
+
if (this.updateTimer) {
|
|
2669
|
+
clearInterval(this.updateTimer);
|
|
2670
|
+
this.updateTimer = null;
|
|
2671
|
+
}
|
|
2672
|
+
}
|
|
2673
|
+
/**
|
|
2674
|
+
* Get cached time in nanoseconds (fast, no syscall)
|
|
2675
|
+
*/
|
|
2676
|
+
nowNs() {
|
|
2677
|
+
return this.cachedTimeNs;
|
|
2678
|
+
}
|
|
2679
|
+
/**
|
|
2680
|
+
* Get cached time in microseconds (fast, no syscall)
|
|
2681
|
+
*/
|
|
2682
|
+
nowUs() {
|
|
2683
|
+
return this.cachedTimeNs / BigInt(1e3);
|
|
2684
|
+
}
|
|
2685
|
+
/**
|
|
2686
|
+
* Get cached time in milliseconds (fast, no syscall)
|
|
2687
|
+
*/
|
|
2688
|
+
nowMs() {
|
|
2689
|
+
return this.cachedTimeMs;
|
|
2690
|
+
}
|
|
2691
|
+
/**
|
|
2692
|
+
* Get precise time (may involve syscall)
|
|
2693
|
+
*/
|
|
2694
|
+
preciseNowNs() {
|
|
2695
|
+
if (this.useHighRes && typeof process !== "undefined" && process.hrtime) {
|
|
2696
|
+
const [seconds, nanoseconds] = process.hrtime();
|
|
2697
|
+
return BigInt(seconds) * BigInt(1e9) + BigInt(nanoseconds);
|
|
2698
|
+
}
|
|
2699
|
+
return BigInt(Date.now()) * BigInt(1e6);
|
|
2700
|
+
}
|
|
2701
|
+
/**
|
|
2702
|
+
* Get precise time in microseconds
|
|
2703
|
+
*/
|
|
2704
|
+
preciseNowUs() {
|
|
2705
|
+
return this.preciseNowNs() / BigInt(1e3);
|
|
2706
|
+
}
|
|
2707
|
+
updateTime() {
|
|
2708
|
+
this.cachedTimeNs = this.preciseNowNs();
|
|
2709
|
+
this.cachedTimeMs = Date.now();
|
|
2710
|
+
this.lastUpdateNs = this.cachedTimeNs;
|
|
2711
|
+
}
|
|
2712
|
+
};
|
|
2713
|
+
var SyscallBypassManager = class {
|
|
2714
|
+
config;
|
|
2715
|
+
timeProvider;
|
|
2716
|
+
syscallQueue = [];
|
|
2717
|
+
batchTimer = null;
|
|
2718
|
+
stats;
|
|
2719
|
+
constructor(config = defaultSyscallBypassConfig()) {
|
|
2720
|
+
this.config = config;
|
|
2721
|
+
this.timeProvider = new FastTimeProvider(config.timeCacheIntervalUs);
|
|
2722
|
+
this.stats = {
|
|
2723
|
+
totalCalls: 0,
|
|
2724
|
+
bypassedCalls: 0,
|
|
2725
|
+
batchedCalls: 0,
|
|
2726
|
+
timeSavedNs: BigInt(0)
|
|
2727
|
+
};
|
|
2728
|
+
}
|
|
2729
|
+
/**
|
|
2730
|
+
* Initialize the syscall bypass manager
|
|
2731
|
+
*/
|
|
2732
|
+
initialize() {
|
|
2733
|
+
if (this.config.enableFastTime) {
|
|
2734
|
+
this.timeProvider.start();
|
|
2735
|
+
}
|
|
2736
|
+
if (this.config.enableBatching) {
|
|
2737
|
+
this.startBatching();
|
|
2738
|
+
}
|
|
2739
|
+
}
|
|
2740
|
+
/**
|
|
2741
|
+
* Shutdown the syscall bypass manager
|
|
2742
|
+
*/
|
|
2743
|
+
shutdown() {
|
|
2744
|
+
this.timeProvider.stop();
|
|
2745
|
+
if (this.batchTimer) {
|
|
2746
|
+
clearInterval(this.batchTimer);
|
|
2747
|
+
this.batchTimer = null;
|
|
2748
|
+
}
|
|
2749
|
+
this.flushBatch();
|
|
2750
|
+
}
|
|
2751
|
+
/**
|
|
2752
|
+
* Get fast cached time in nanoseconds
|
|
2753
|
+
*/
|
|
2754
|
+
fastTimeNs() {
|
|
2755
|
+
this.stats.totalCalls++;
|
|
2756
|
+
this.stats.bypassedCalls++;
|
|
2757
|
+
return this.timeProvider.nowNs();
|
|
2758
|
+
}
|
|
2759
|
+
/**
|
|
2760
|
+
* Get fast cached time in microseconds
|
|
2761
|
+
*/
|
|
2762
|
+
fastTimeUs() {
|
|
2763
|
+
return this.timeProvider.nowUs();
|
|
2764
|
+
}
|
|
2765
|
+
/**
|
|
2766
|
+
* Get fast cached time in milliseconds
|
|
2767
|
+
*/
|
|
2768
|
+
fastTimeMs() {
|
|
2769
|
+
return this.timeProvider.nowMs();
|
|
2770
|
+
}
|
|
2771
|
+
/**
|
|
2772
|
+
* Queue a syscall for batching
|
|
2773
|
+
*/
|
|
2774
|
+
queueSyscall(syscall) {
|
|
2775
|
+
if (!this.config.enableBatching) {
|
|
2776
|
+
syscall();
|
|
2777
|
+
return;
|
|
2778
|
+
}
|
|
2779
|
+
this.syscallQueue.push(syscall);
|
|
2780
|
+
this.stats.batchedCalls++;
|
|
2781
|
+
if (this.syscallQueue.length >= this.config.maxBatchSize) {
|
|
2782
|
+
this.flushBatch();
|
|
2783
|
+
}
|
|
2784
|
+
}
|
|
2785
|
+
/**
|
|
2786
|
+
* Execute a function with syscall bypass timing
|
|
2787
|
+
*/
|
|
2788
|
+
measure(fn) {
|
|
2789
|
+
const start = this.timeProvider.preciseNowNs();
|
|
2790
|
+
const result = fn();
|
|
2791
|
+
const elapsed = this.timeProvider.preciseNowNs() - start;
|
|
2792
|
+
return { result, elapsedNs: elapsed };
|
|
2793
|
+
}
|
|
2794
|
+
/**
|
|
2795
|
+
* Get syscall bypass statistics
|
|
2796
|
+
*/
|
|
2797
|
+
getStats() {
|
|
2798
|
+
const bypassRate = this.stats.totalCalls > 0 ? this.stats.bypassedCalls / this.stats.totalCalls : 0;
|
|
2799
|
+
return {
|
|
2800
|
+
...this.stats,
|
|
2801
|
+
bypassRate
|
|
2802
|
+
};
|
|
2803
|
+
}
|
|
2804
|
+
/**
|
|
2805
|
+
* Reset statistics
|
|
2806
|
+
*/
|
|
2807
|
+
resetStats() {
|
|
2808
|
+
this.stats = {
|
|
2809
|
+
totalCalls: 0,
|
|
2810
|
+
bypassedCalls: 0,
|
|
2811
|
+
batchedCalls: 0,
|
|
2812
|
+
timeSavedNs: BigInt(0)
|
|
2813
|
+
};
|
|
2814
|
+
}
|
|
2815
|
+
startBatching() {
|
|
2816
|
+
this.batchTimer = setInterval(() => {
|
|
2817
|
+
this.flushBatch();
|
|
2818
|
+
}, 1);
|
|
2819
|
+
}
|
|
2820
|
+
flushBatch() {
|
|
2821
|
+
while (this.syscallQueue.length > 0) {
|
|
2822
|
+
const syscall = this.syscallQueue.shift();
|
|
2823
|
+
if (syscall) {
|
|
2824
|
+
try {
|
|
2825
|
+
syscall();
|
|
2826
|
+
} catch (error) {
|
|
2827
|
+
console.error("Batched syscall error:", error);
|
|
2828
|
+
}
|
|
2829
|
+
}
|
|
2830
|
+
}
|
|
2831
|
+
}
|
|
2832
|
+
};
|
|
2833
|
+
function createSyscallBypassManager(config) {
|
|
2834
|
+
const fullConfig = { ...defaultSyscallBypassConfig(), ...config };
|
|
2835
|
+
return new SyscallBypassManager(fullConfig);
|
|
2836
|
+
}
|
|
2837
|
+
var globalTimeProvider = null;
|
|
2838
|
+
function getGlobalTimeProvider() {
|
|
2839
|
+
if (!globalTimeProvider) {
|
|
2840
|
+
globalTimeProvider = new FastTimeProvider();
|
|
2841
|
+
globalTimeProvider.start();
|
|
2842
|
+
}
|
|
2843
|
+
return globalTimeProvider;
|
|
2844
|
+
}
|
|
2845
|
+
function fastNowNs() {
|
|
2846
|
+
return getGlobalTimeProvider().nowNs();
|
|
2847
|
+
}
|
|
2848
|
+
function fastNowUs() {
|
|
2849
|
+
return getGlobalTimeProvider().nowUs();
|
|
2850
|
+
}
|
|
2851
|
+
function fastNowMs() {
|
|
2852
|
+
return getGlobalTimeProvider().nowMs();
|
|
2853
|
+
}
|
|
2854
|
+
|
|
2855
|
+
// src/perf/ultra-low-latency.ts
|
|
2856
|
+
function defaultUltraLowLatencyConfig() {
|
|
2857
|
+
return {
|
|
2858
|
+
memoryPoolSize: 1024,
|
|
2859
|
+
queueCapacity: 4096,
|
|
2860
|
+
enableBusySpin: true,
|
|
2861
|
+
spinCount: 1e3,
|
|
2862
|
+
enablePrefetch: true,
|
|
2863
|
+
numaAware: false
|
|
2864
|
+
};
|
|
2865
|
+
}
|
|
2866
|
+
var MemoryPool = class {
|
|
2867
|
+
pool = [];
|
|
2868
|
+
factory;
|
|
2869
|
+
resetFn;
|
|
2870
|
+
maxSize;
|
|
2871
|
+
leased = 0;
|
|
2872
|
+
constructor(factory, resetFn, maxSize = 1024) {
|
|
2873
|
+
this.factory = factory;
|
|
2874
|
+
this.resetFn = resetFn;
|
|
2875
|
+
this.maxSize = maxSize;
|
|
2876
|
+
for (let i = 0; i < maxSize; i++) {
|
|
2877
|
+
this.pool.push(factory());
|
|
2878
|
+
}
|
|
2879
|
+
}
|
|
2880
|
+
/**
|
|
2881
|
+
* Acquire an object from the pool
|
|
2882
|
+
*/
|
|
2883
|
+
acquire() {
|
|
2884
|
+
this.leased++;
|
|
2885
|
+
if (this.pool.length > 0) {
|
|
2886
|
+
return this.pool.pop();
|
|
2887
|
+
}
|
|
2888
|
+
return this.factory();
|
|
2889
|
+
}
|
|
2890
|
+
/**
|
|
2891
|
+
* Release an object back to the pool
|
|
2892
|
+
*/
|
|
2893
|
+
release(obj) {
|
|
2894
|
+
if (this.leased <= 0) return;
|
|
2895
|
+
this.leased--;
|
|
2896
|
+
if (this.pool.length < this.maxSize) {
|
|
2897
|
+
this.resetFn(obj);
|
|
2898
|
+
this.pool.push(obj);
|
|
2899
|
+
}
|
|
2900
|
+
}
|
|
2901
|
+
/**
|
|
2902
|
+
* Execute a function with a pooled object
|
|
2903
|
+
*/
|
|
2904
|
+
with(fn) {
|
|
2905
|
+
const obj = this.acquire();
|
|
2906
|
+
try {
|
|
2907
|
+
return fn(obj);
|
|
2908
|
+
} finally {
|
|
2909
|
+
this.release(obj);
|
|
2910
|
+
}
|
|
2911
|
+
}
|
|
2912
|
+
/**
|
|
2913
|
+
* Get pool statistics
|
|
2914
|
+
*/
|
|
2915
|
+
getStats() {
|
|
2916
|
+
return {
|
|
2917
|
+
available: this.pool.length,
|
|
2918
|
+
inUse: this.leased,
|
|
2919
|
+
total: this.pool.length + this.leased
|
|
2920
|
+
};
|
|
2921
|
+
}
|
|
2922
|
+
};
|
|
2923
|
+
var LockFreeQueue = class {
|
|
2924
|
+
buffer;
|
|
2925
|
+
capacity;
|
|
2926
|
+
mask;
|
|
2927
|
+
head = 0;
|
|
2928
|
+
// Write position
|
|
2929
|
+
tail = 0;
|
|
2930
|
+
// Read position
|
|
2931
|
+
config;
|
|
2932
|
+
constructor(capacity = 4096, config) {
|
|
2933
|
+
this.capacity = Math.pow(2, Math.ceil(Math.log2(capacity)));
|
|
2934
|
+
this.mask = this.capacity - 1;
|
|
2935
|
+
this.buffer = new Array(this.capacity).fill(void 0);
|
|
2936
|
+
this.config = config || defaultUltraLowLatencyConfig();
|
|
2937
|
+
}
|
|
2938
|
+
/**
|
|
2939
|
+
* Enqueue an item (producer only)
|
|
2940
|
+
*/
|
|
2941
|
+
enqueue(item) {
|
|
2942
|
+
const nextHead = this.head + 1 & this.mask;
|
|
2943
|
+
if (nextHead === this.tail) {
|
|
2944
|
+
return false;
|
|
2945
|
+
}
|
|
2946
|
+
this.buffer[this.head] = item;
|
|
2947
|
+
this.head = nextHead;
|
|
2948
|
+
return true;
|
|
2949
|
+
}
|
|
2950
|
+
/**
|
|
2951
|
+
* Dequeue an item (consumer only)
|
|
2952
|
+
*/
|
|
2953
|
+
dequeue() {
|
|
2954
|
+
if (this.tail === this.head) {
|
|
2955
|
+
return void 0;
|
|
2956
|
+
}
|
|
2957
|
+
const item = this.buffer[this.tail];
|
|
2958
|
+
this.buffer[this.tail] = void 0;
|
|
2959
|
+
this.tail = this.tail + 1 & this.mask;
|
|
2960
|
+
return item;
|
|
2961
|
+
}
|
|
2962
|
+
/**
|
|
2963
|
+
* Try dequeue with spinning
|
|
2964
|
+
*/
|
|
2965
|
+
dequeueSpin(timeoutUs = 1e3) {
|
|
2966
|
+
const startTime = performance.now();
|
|
2967
|
+
const timeoutMs = timeoutUs / 1e3;
|
|
2968
|
+
let spins = 0;
|
|
2969
|
+
while (performance.now() - startTime < timeoutMs) {
|
|
2970
|
+
const item = this.dequeue();
|
|
2971
|
+
if (item !== void 0) {
|
|
2972
|
+
return item;
|
|
2973
|
+
}
|
|
2974
|
+
if (this.config.enableBusySpin && spins < this.config.spinCount) {
|
|
2975
|
+
spins++;
|
|
2976
|
+
continue;
|
|
2977
|
+
}
|
|
2978
|
+
spins = 0;
|
|
2979
|
+
}
|
|
2980
|
+
return void 0;
|
|
2981
|
+
}
|
|
2982
|
+
/**
|
|
2983
|
+
* Get current size
|
|
2984
|
+
*/
|
|
2985
|
+
size() {
|
|
2986
|
+
return this.head - this.tail & this.mask;
|
|
2987
|
+
}
|
|
2988
|
+
/**
|
|
2989
|
+
* Check if empty
|
|
2990
|
+
*/
|
|
2991
|
+
isEmpty() {
|
|
2992
|
+
return this.head === this.tail;
|
|
2993
|
+
}
|
|
2994
|
+
/**
|
|
2995
|
+
* Check if full
|
|
2996
|
+
*/
|
|
2997
|
+
isFull() {
|
|
2998
|
+
return (this.head + 1 & this.mask) === this.tail;
|
|
2999
|
+
}
|
|
3000
|
+
/**
|
|
3001
|
+
* Clear the queue
|
|
3002
|
+
*/
|
|
3003
|
+
clear() {
|
|
3004
|
+
this.head = 0;
|
|
3005
|
+
this.tail = 0;
|
|
3006
|
+
this.buffer.fill(void 0);
|
|
3007
|
+
}
|
|
3008
|
+
};
|
|
3009
|
+
var MPMCQueue = class {
|
|
3010
|
+
buffer;
|
|
3011
|
+
capacity;
|
|
3012
|
+
mask;
|
|
3013
|
+
enqueuePos = 0;
|
|
3014
|
+
dequeuePos = 0;
|
|
3015
|
+
constructor(capacity = 4096) {
|
|
3016
|
+
this.capacity = Math.pow(2, Math.ceil(Math.log2(capacity)));
|
|
3017
|
+
this.mask = this.capacity - 1;
|
|
3018
|
+
this.buffer = new Array(this.capacity);
|
|
3019
|
+
for (let i = 0; i < this.capacity; i++) {
|
|
3020
|
+
this.buffer[i] = { item: void 0, sequence: i };
|
|
3021
|
+
}
|
|
3022
|
+
}
|
|
3023
|
+
/**
|
|
3024
|
+
* Enqueue an item (thread-safe)
|
|
3025
|
+
*/
|
|
3026
|
+
enqueue(item) {
|
|
3027
|
+
let pos = this.enqueuePos;
|
|
3028
|
+
while (true) {
|
|
3029
|
+
const slot = this.buffer[pos & this.mask];
|
|
3030
|
+
const seq = slot.sequence;
|
|
3031
|
+
const diff = seq - pos;
|
|
3032
|
+
if (diff === 0) {
|
|
3033
|
+
if (this.compareAndSwapEnqueuePos(pos, pos + 1)) {
|
|
3034
|
+
slot.item = item;
|
|
3035
|
+
slot.sequence = pos + 1;
|
|
3036
|
+
return true;
|
|
3037
|
+
}
|
|
3038
|
+
pos = this.enqueuePos;
|
|
3039
|
+
} else if (diff < 0) {
|
|
3040
|
+
return false;
|
|
3041
|
+
} else {
|
|
3042
|
+
pos = this.enqueuePos;
|
|
3043
|
+
}
|
|
3044
|
+
}
|
|
3045
|
+
}
|
|
3046
|
+
/**
|
|
3047
|
+
* Dequeue an item (thread-safe)
|
|
3048
|
+
*/
|
|
3049
|
+
dequeue() {
|
|
3050
|
+
let pos = this.dequeuePos;
|
|
3051
|
+
while (true) {
|
|
3052
|
+
const slot = this.buffer[pos & this.mask];
|
|
3053
|
+
const seq = slot.sequence;
|
|
3054
|
+
const diff = seq - (pos + 1);
|
|
3055
|
+
if (diff === 0) {
|
|
3056
|
+
if (this.compareAndSwapDequeuePos(pos, pos + 1)) {
|
|
3057
|
+
const item = slot.item;
|
|
3058
|
+
slot.item = void 0;
|
|
3059
|
+
slot.sequence = pos + this.mask + 1;
|
|
3060
|
+
return item;
|
|
3061
|
+
}
|
|
3062
|
+
pos = this.dequeuePos;
|
|
3063
|
+
} else if (diff < 0) {
|
|
3064
|
+
return void 0;
|
|
3065
|
+
} else {
|
|
3066
|
+
pos = this.dequeuePos;
|
|
3067
|
+
}
|
|
3068
|
+
}
|
|
3069
|
+
}
|
|
3070
|
+
compareAndSwapEnqueuePos(expected, value) {
|
|
3071
|
+
if (this.enqueuePos === expected) {
|
|
3072
|
+
this.enqueuePos = value;
|
|
3073
|
+
return true;
|
|
3074
|
+
}
|
|
3075
|
+
return false;
|
|
3076
|
+
}
|
|
3077
|
+
compareAndSwapDequeuePos(expected, value) {
|
|
3078
|
+
if (this.dequeuePos === expected) {
|
|
3079
|
+
this.dequeuePos = value;
|
|
3080
|
+
return true;
|
|
3081
|
+
}
|
|
3082
|
+
return false;
|
|
3083
|
+
}
|
|
3084
|
+
};
|
|
3085
|
+
var LatencyOptimizer = class {
|
|
3086
|
+
latencies = [];
|
|
3087
|
+
maxSamples;
|
|
3088
|
+
config;
|
|
3089
|
+
optimizationCallbacks = [];
|
|
3090
|
+
constructor(maxSamples = 1e4, config) {
|
|
3091
|
+
this.maxSamples = maxSamples;
|
|
3092
|
+
this.config = config || defaultUltraLowLatencyConfig();
|
|
3093
|
+
}
|
|
3094
|
+
/**
|
|
3095
|
+
* Record a latency measurement
|
|
3096
|
+
*/
|
|
3097
|
+
recordLatency(latencyUs) {
|
|
3098
|
+
this.latencies.push(latencyUs);
|
|
3099
|
+
if (this.latencies.length > this.maxSamples) {
|
|
3100
|
+
this.latencies.shift();
|
|
3101
|
+
}
|
|
3102
|
+
}
|
|
3103
|
+
/**
|
|
3104
|
+
* Measure and record function execution time
|
|
3105
|
+
*/
|
|
3106
|
+
measure(fn) {
|
|
3107
|
+
const start = performance.now();
|
|
3108
|
+
const result = fn();
|
|
3109
|
+
const latencyUs = (performance.now() - start) * 1e3;
|
|
3110
|
+
this.recordLatency(latencyUs);
|
|
3111
|
+
return { result, latencyUs };
|
|
3112
|
+
}
|
|
3113
|
+
/**
|
|
3114
|
+
* Get latency statistics
|
|
3115
|
+
*/
|
|
3116
|
+
getStats() {
|
|
3117
|
+
if (this.latencies.length === 0) {
|
|
3118
|
+
return {
|
|
3119
|
+
minLatencyUs: 0,
|
|
3120
|
+
maxLatencyUs: 0,
|
|
3121
|
+
avgLatencyUs: 0,
|
|
3122
|
+
p50LatencyUs: 0,
|
|
3123
|
+
p99LatencyUs: 0,
|
|
3124
|
+
p999LatencyUs: 0,
|
|
3125
|
+
totalOperations: 0
|
|
3126
|
+
};
|
|
3127
|
+
}
|
|
3128
|
+
const sorted = [...this.latencies].sort((a, b) => a - b);
|
|
3129
|
+
const n = sorted.length;
|
|
3130
|
+
return {
|
|
3131
|
+
minLatencyUs: sorted[0] ?? 0,
|
|
3132
|
+
maxLatencyUs: sorted[n - 1] ?? 0,
|
|
3133
|
+
avgLatencyUs: sorted.reduce((a, b) => a + b, 0) / n,
|
|
3134
|
+
p50LatencyUs: sorted[Math.floor(n * 0.5)] ?? 0,
|
|
3135
|
+
p99LatencyUs: sorted[Math.floor(n * 0.99)] ?? 0,
|
|
3136
|
+
p999LatencyUs: sorted[Math.floor(n * 0.999)] ?? 0,
|
|
3137
|
+
totalOperations: n
|
|
3138
|
+
};
|
|
3139
|
+
}
|
|
3140
|
+
/**
|
|
3141
|
+
* Register an optimization callback
|
|
3142
|
+
*/
|
|
3143
|
+
onOptimization(callback) {
|
|
3144
|
+
this.optimizationCallbacks.push(callback);
|
|
3145
|
+
}
|
|
3146
|
+
/**
|
|
3147
|
+
* Trigger optimization
|
|
3148
|
+
*/
|
|
3149
|
+
optimize() {
|
|
3150
|
+
for (const callback of this.optimizationCallbacks) {
|
|
3151
|
+
try {
|
|
3152
|
+
callback();
|
|
3153
|
+
} catch (error) {
|
|
3154
|
+
console.error("Optimization callback error:", error);
|
|
3155
|
+
}
|
|
3156
|
+
}
|
|
3157
|
+
}
|
|
3158
|
+
/**
|
|
3159
|
+
* Reset statistics
|
|
3160
|
+
*/
|
|
3161
|
+
reset() {
|
|
3162
|
+
this.latencies = [];
|
|
3163
|
+
}
|
|
3164
|
+
};
|
|
3165
|
+
function prefetch(obj) {
|
|
3166
|
+
if (obj && typeof obj === "object") {
|
|
3167
|
+
const key = Object.keys(obj)[0];
|
|
3168
|
+
const _ = key === void 0 ? void 0 : obj[key];
|
|
3169
|
+
}
|
|
3170
|
+
}
|
|
3171
|
+
function prefetchArray(arr, index) {
|
|
3172
|
+
const _ = arr[index];
|
|
3173
|
+
}
|
|
3174
|
+
function createMemoryPool(factory, resetFn, size) {
|
|
3175
|
+
return new MemoryPool(factory, resetFn, size || defaultUltraLowLatencyConfig().memoryPoolSize);
|
|
3176
|
+
}
|
|
3177
|
+
function createLockFreeQueue(capacity) {
|
|
3178
|
+
return new LockFreeQueue(capacity);
|
|
3179
|
+
}
|
|
3180
|
+
function createMPMCQueue(capacity) {
|
|
3181
|
+
return new MPMCQueue(capacity);
|
|
3182
|
+
}
|
|
3183
|
+
function busySpin(iterations) {
|
|
3184
|
+
for (let i = 0; i < iterations; i++) {
|
|
3185
|
+
Math.random();
|
|
3186
|
+
}
|
|
3187
|
+
}
|
|
3188
|
+
function yieldToEventLoop() {
|
|
3189
|
+
return new Promise((resolve) => setImmediate(resolve));
|
|
3190
|
+
}
|
|
3191
|
+
|
|
3192
|
+
// src/perf/zero-copy.ts
|
|
3193
|
+
function defaultBufferPoolConfig() {
|
|
3194
|
+
return {
|
|
3195
|
+
bufferSize: 4096,
|
|
3196
|
+
poolSize: 128,
|
|
3197
|
+
autoExpand: true,
|
|
3198
|
+
maxPoolSize: 1024
|
|
3199
|
+
};
|
|
3200
|
+
}
|
|
3201
|
+
var ZeroCopyBuffer = class _ZeroCopyBuffer {
|
|
3202
|
+
buffer;
|
|
3203
|
+
view;
|
|
3204
|
+
uint8View;
|
|
3205
|
+
offset = 0;
|
|
3206
|
+
constructor(size = 4096) {
|
|
3207
|
+
this.buffer = new ArrayBuffer(size);
|
|
3208
|
+
this.view = new DataView(this.buffer);
|
|
3209
|
+
this.uint8View = new Uint8Array(this.buffer);
|
|
3210
|
+
}
|
|
3211
|
+
/**
|
|
3212
|
+
* Create from existing buffer (zero-copy)
|
|
3213
|
+
*/
|
|
3214
|
+
static from(buffer) {
|
|
3215
|
+
const zc = new _ZeroCopyBuffer(0);
|
|
3216
|
+
zc.buffer = buffer;
|
|
3217
|
+
zc.view = new DataView(buffer);
|
|
3218
|
+
zc.uint8View = new Uint8Array(buffer);
|
|
3219
|
+
return zc;
|
|
3220
|
+
}
|
|
3221
|
+
/**
|
|
3222
|
+
* Create a view into this buffer without copying
|
|
3223
|
+
*/
|
|
3224
|
+
slice(start, end) {
|
|
3225
|
+
return new Uint8Array(this.buffer, start, end - start);
|
|
3226
|
+
}
|
|
3227
|
+
/**
|
|
3228
|
+
* Get current write offset
|
|
3229
|
+
*/
|
|
3230
|
+
getOffset() {
|
|
3231
|
+
return this.offset;
|
|
3232
|
+
}
|
|
3233
|
+
/**
|
|
3234
|
+
* Set write offset
|
|
3235
|
+
*/
|
|
3236
|
+
setOffset(offset) {
|
|
3237
|
+
this.offset = offset;
|
|
3238
|
+
}
|
|
3239
|
+
/**
|
|
3240
|
+
* Get buffer capacity
|
|
3241
|
+
*/
|
|
3242
|
+
capacity() {
|
|
3243
|
+
return this.buffer.byteLength;
|
|
3244
|
+
}
|
|
3245
|
+
/**
|
|
3246
|
+
* Write Uint8 at current offset
|
|
3247
|
+
*/
|
|
3248
|
+
writeUint8(value) {
|
|
3249
|
+
this.view.setUint8(this.offset, value);
|
|
3250
|
+
this.offset += 1;
|
|
3251
|
+
}
|
|
3252
|
+
/**
|
|
3253
|
+
* Write Uint16 at current offset (little-endian)
|
|
3254
|
+
*/
|
|
3255
|
+
writeUint16(value) {
|
|
3256
|
+
this.view.setUint16(this.offset, value, true);
|
|
3257
|
+
this.offset += 2;
|
|
3258
|
+
}
|
|
3259
|
+
/**
|
|
3260
|
+
* Write Uint32 at current offset (little-endian)
|
|
3261
|
+
*/
|
|
3262
|
+
writeUint32(value) {
|
|
3263
|
+
this.view.setUint32(this.offset, value, true);
|
|
3264
|
+
this.offset += 4;
|
|
3265
|
+
}
|
|
3266
|
+
/**
|
|
3267
|
+
* Write BigUint64 at current offset (little-endian)
|
|
3268
|
+
*/
|
|
3269
|
+
writeUint64(value) {
|
|
3270
|
+
this.view.setBigUint64(this.offset, value, true);
|
|
3271
|
+
this.offset += 8;
|
|
3272
|
+
}
|
|
3273
|
+
/**
|
|
3274
|
+
* Write bytes at current offset
|
|
3275
|
+
*/
|
|
3276
|
+
writeBytes(bytes) {
|
|
3277
|
+
this.uint8View.set(bytes, this.offset);
|
|
3278
|
+
this.offset += bytes.length;
|
|
3279
|
+
}
|
|
3280
|
+
/**
|
|
3281
|
+
* Read Uint8 at offset
|
|
3282
|
+
*/
|
|
3283
|
+
readUint8(offset) {
|
|
3284
|
+
return this.view.getUint8(offset);
|
|
3285
|
+
}
|
|
3286
|
+
/**
|
|
3287
|
+
* Read Uint16 at offset (little-endian)
|
|
3288
|
+
*/
|
|
3289
|
+
readUint16(offset) {
|
|
3290
|
+
return this.view.getUint16(offset, true);
|
|
3291
|
+
}
|
|
3292
|
+
/**
|
|
3293
|
+
* Read Uint32 at offset (little-endian)
|
|
3294
|
+
*/
|
|
3295
|
+
readUint32(offset) {
|
|
3296
|
+
return this.view.getUint32(offset, true);
|
|
3297
|
+
}
|
|
3298
|
+
/**
|
|
3299
|
+
* Read BigUint64 at offset (little-endian)
|
|
3300
|
+
*/
|
|
3301
|
+
readUint64(offset) {
|
|
3302
|
+
return this.view.getBigUint64(offset, true);
|
|
3303
|
+
}
|
|
3304
|
+
/**
|
|
3305
|
+
* Read bytes at offset
|
|
3306
|
+
*/
|
|
3307
|
+
readBytes(offset, length) {
|
|
3308
|
+
return new Uint8Array(this.buffer, offset, length);
|
|
3309
|
+
}
|
|
3310
|
+
/**
|
|
3311
|
+
* Get the underlying ArrayBuffer
|
|
3312
|
+
*/
|
|
3313
|
+
getBuffer() {
|
|
3314
|
+
return this.buffer;
|
|
3315
|
+
}
|
|
3316
|
+
/**
|
|
3317
|
+
* Get as Uint8Array (full buffer)
|
|
3318
|
+
*/
|
|
3319
|
+
asUint8Array() {
|
|
3320
|
+
return this.uint8View;
|
|
3321
|
+
}
|
|
3322
|
+
/**
|
|
3323
|
+
* Get used portion as Uint8Array (zero-copy view)
|
|
3324
|
+
*/
|
|
3325
|
+
asUsedUint8Array() {
|
|
3326
|
+
return new Uint8Array(this.buffer, 0, this.offset);
|
|
3327
|
+
}
|
|
3328
|
+
/**
|
|
3329
|
+
* Reset offset to beginning
|
|
3330
|
+
*/
|
|
3331
|
+
reset() {
|
|
3332
|
+
this.offset = 0;
|
|
3333
|
+
}
|
|
3334
|
+
/**
|
|
3335
|
+
* Ensure capacity (creates new buffer if needed, copies data)
|
|
3336
|
+
*/
|
|
3337
|
+
ensureCapacity(minCapacity) {
|
|
3338
|
+
if (this.buffer.byteLength >= minCapacity) {
|
|
3339
|
+
return;
|
|
3340
|
+
}
|
|
3341
|
+
const newCapacity = Math.max(minCapacity, this.buffer.byteLength * 2);
|
|
3342
|
+
const newBuffer = new ArrayBuffer(newCapacity);
|
|
3343
|
+
const newUint8 = new Uint8Array(newBuffer);
|
|
3344
|
+
newUint8.set(this.uint8View);
|
|
3345
|
+
this.buffer = newBuffer;
|
|
3346
|
+
this.view = new DataView(newBuffer);
|
|
3347
|
+
this.uint8View = newUint8;
|
|
3348
|
+
}
|
|
3349
|
+
};
|
|
3350
|
+
var BufferPool = class {
|
|
3351
|
+
pool = [];
|
|
3352
|
+
inUse = /* @__PURE__ */ new Set();
|
|
3353
|
+
config;
|
|
3354
|
+
constructor(config = defaultBufferPoolConfig()) {
|
|
3355
|
+
this.config = config;
|
|
3356
|
+
for (let i = 0; i < config.poolSize; i++) {
|
|
3357
|
+
this.pool.push(new ArrayBuffer(config.bufferSize));
|
|
3358
|
+
}
|
|
3359
|
+
}
|
|
3360
|
+
/**
|
|
3361
|
+
* Acquire a buffer from the pool
|
|
3362
|
+
*/
|
|
3363
|
+
acquire() {
|
|
3364
|
+
if (this.pool.length > 0) {
|
|
3365
|
+
const buffer = this.pool.pop();
|
|
3366
|
+
this.inUse.add(buffer);
|
|
3367
|
+
return buffer;
|
|
3368
|
+
}
|
|
3369
|
+
if (this.config.autoExpand && this.pool.length + this.inUse.size < this.config.maxPoolSize) {
|
|
3370
|
+
const buffer = new ArrayBuffer(this.config.bufferSize);
|
|
3371
|
+
this.inUse.add(buffer);
|
|
3372
|
+
return buffer;
|
|
3373
|
+
}
|
|
3374
|
+
throw new Error("Buffer pool exhausted");
|
|
3375
|
+
}
|
|
3376
|
+
/**
|
|
3377
|
+
* Acquire a ZeroCopyBuffer wrapper
|
|
3378
|
+
*/
|
|
3379
|
+
acquireZeroCopyBuffer() {
|
|
3380
|
+
const buffer = this.acquire();
|
|
3381
|
+
return ZeroCopyBuffer.from(buffer);
|
|
3382
|
+
}
|
|
3383
|
+
/**
|
|
3384
|
+
* Release a buffer back to the pool
|
|
3385
|
+
*/
|
|
3386
|
+
release(buffer) {
|
|
3387
|
+
if (!this.inUse.has(buffer)) {
|
|
3388
|
+
return;
|
|
3389
|
+
}
|
|
3390
|
+
this.inUse.delete(buffer);
|
|
3391
|
+
if (this.pool.length < this.config.maxPoolSize) {
|
|
3392
|
+
this.pool.push(buffer);
|
|
3393
|
+
}
|
|
3394
|
+
}
|
|
3395
|
+
/**
|
|
3396
|
+
* Execute a function with a pooled buffer
|
|
3397
|
+
*/
|
|
3398
|
+
with(fn) {
|
|
3399
|
+
const buffer = this.acquire();
|
|
3400
|
+
try {
|
|
3401
|
+
return fn(buffer);
|
|
3402
|
+
} finally {
|
|
3403
|
+
this.release(buffer);
|
|
3404
|
+
}
|
|
3405
|
+
}
|
|
3406
|
+
/**
|
|
3407
|
+
* Get pool statistics
|
|
3408
|
+
*/
|
|
3409
|
+
getStats() {
|
|
3410
|
+
return {
|
|
3411
|
+
available: this.pool.length,
|
|
3412
|
+
inUse: this.inUse.size,
|
|
3413
|
+
total: this.pool.length + this.inUse.size
|
|
3414
|
+
};
|
|
3415
|
+
}
|
|
3416
|
+
/**
|
|
3417
|
+
* Clear all buffers
|
|
3418
|
+
*/
|
|
3419
|
+
clear() {
|
|
3420
|
+
this.pool = [];
|
|
3421
|
+
this.inUse.clear();
|
|
3422
|
+
}
|
|
3423
|
+
};
|
|
3424
|
+
var ZeroCopySerializer = class {
|
|
3425
|
+
buffer;
|
|
3426
|
+
textEncoder;
|
|
3427
|
+
textDecoder;
|
|
3428
|
+
constructor(initialSize = 4096) {
|
|
3429
|
+
this.buffer = new ZeroCopyBuffer(initialSize);
|
|
3430
|
+
this.textEncoder = new TextEncoder();
|
|
3431
|
+
this.textDecoder = new TextDecoder();
|
|
3432
|
+
}
|
|
3433
|
+
/**
|
|
3434
|
+
* Serialize a string (length-prefixed)
|
|
3435
|
+
*/
|
|
3436
|
+
writeString(value) {
|
|
3437
|
+
const bytes = this.textEncoder.encode(value);
|
|
3438
|
+
this.buffer.writeUint32(bytes.length);
|
|
3439
|
+
this.buffer.writeBytes(bytes);
|
|
3440
|
+
}
|
|
3441
|
+
/**
|
|
3442
|
+
* Serialize a PublicKey (32 bytes)
|
|
3443
|
+
*/
|
|
3444
|
+
writePublicKey(bytes) {
|
|
3445
|
+
if (bytes.length !== 32) {
|
|
3446
|
+
throw new Error("PublicKey must be 32 bytes");
|
|
3447
|
+
}
|
|
3448
|
+
this.buffer.writeBytes(bytes);
|
|
3449
|
+
}
|
|
3450
|
+
/**
|
|
3451
|
+
* Serialize a BigInt (8 bytes)
|
|
3452
|
+
*/
|
|
3453
|
+
writeBigInt(value) {
|
|
3454
|
+
this.buffer.writeUint64(value);
|
|
3455
|
+
}
|
|
3456
|
+
/**
|
|
3457
|
+
* Serialize a number (4 bytes)
|
|
3458
|
+
*/
|
|
3459
|
+
writeNumber(value) {
|
|
3460
|
+
this.buffer.writeUint32(value);
|
|
3461
|
+
}
|
|
3462
|
+
/**
|
|
3463
|
+
* Serialize a boolean (1 byte)
|
|
3464
|
+
*/
|
|
3465
|
+
writeBoolean(value) {
|
|
3466
|
+
this.buffer.writeUint8(value ? 1 : 0);
|
|
3467
|
+
}
|
|
3468
|
+
/**
|
|
3469
|
+
* Serialize bytes with length prefix
|
|
3470
|
+
*/
|
|
3471
|
+
writeByteArray(bytes) {
|
|
3472
|
+
this.buffer.writeUint32(bytes.length);
|
|
3473
|
+
this.buffer.writeBytes(bytes);
|
|
3474
|
+
}
|
|
3475
|
+
/**
|
|
3476
|
+
* Deserialize a string
|
|
3477
|
+
*/
|
|
3478
|
+
readString(offset) {
|
|
3479
|
+
const length = this.buffer.readUint32(offset);
|
|
3480
|
+
const bytes = this.buffer.readBytes(offset + 4, length);
|
|
3481
|
+
const value = this.textDecoder.decode(bytes);
|
|
3482
|
+
return { value, nextOffset: offset + 4 + length };
|
|
3483
|
+
}
|
|
3484
|
+
/**
|
|
3485
|
+
* Deserialize a PublicKey
|
|
3486
|
+
*/
|
|
3487
|
+
readPublicKey(offset) {
|
|
3488
|
+
const value = this.buffer.readBytes(offset, 32);
|
|
3489
|
+
return { value, nextOffset: offset + 32 };
|
|
3490
|
+
}
|
|
3491
|
+
/**
|
|
3492
|
+
* Deserialize a BigInt
|
|
3493
|
+
*/
|
|
3494
|
+
readBigInt(offset) {
|
|
3495
|
+
const value = this.buffer.readUint64(offset);
|
|
3496
|
+
return { value, nextOffset: offset + 8 };
|
|
3497
|
+
}
|
|
3498
|
+
/**
|
|
3499
|
+
* Deserialize a number
|
|
3500
|
+
*/
|
|
3501
|
+
readNumber(offset) {
|
|
3502
|
+
const value = this.buffer.readUint32(offset);
|
|
3503
|
+
return { value, nextOffset: offset + 4 };
|
|
3504
|
+
}
|
|
3505
|
+
/**
|
|
3506
|
+
* Deserialize a boolean
|
|
3507
|
+
*/
|
|
3508
|
+
readBoolean(offset) {
|
|
3509
|
+
const value = this.buffer.readUint8(offset) !== 0;
|
|
3510
|
+
return { value, nextOffset: offset + 1 };
|
|
3511
|
+
}
|
|
3512
|
+
/**
|
|
3513
|
+
* Deserialize a byte array
|
|
3514
|
+
*/
|
|
3515
|
+
readByteArray(offset) {
|
|
3516
|
+
const length = this.buffer.readUint32(offset);
|
|
3517
|
+
const value = this.buffer.readBytes(offset + 4, length);
|
|
3518
|
+
return { value, nextOffset: offset + 4 + length };
|
|
3519
|
+
}
|
|
3520
|
+
/**
|
|
3521
|
+
* Get serialized data as Uint8Array (zero-copy view)
|
|
3522
|
+
*/
|
|
3523
|
+
getData() {
|
|
3524
|
+
return this.buffer.asUsedUint8Array();
|
|
3525
|
+
}
|
|
3526
|
+
/**
|
|
3527
|
+
* Reset for reuse
|
|
3528
|
+
*/
|
|
3529
|
+
reset() {
|
|
3530
|
+
this.buffer.reset();
|
|
3531
|
+
}
|
|
3532
|
+
/**
|
|
3533
|
+
* Get current offset
|
|
3534
|
+
*/
|
|
3535
|
+
getOffset() {
|
|
3536
|
+
return this.buffer.getOffset();
|
|
3537
|
+
}
|
|
3538
|
+
};
|
|
3539
|
+
var FixedBufferView = class {
|
|
3540
|
+
buffer;
|
|
3541
|
+
view;
|
|
3542
|
+
uint8View;
|
|
3543
|
+
baseOffset;
|
|
3544
|
+
constructor(buffer, offset, size) {
|
|
3545
|
+
this.buffer = buffer;
|
|
3546
|
+
this.view = new DataView(buffer, offset, size);
|
|
3547
|
+
this.uint8View = new Uint8Array(buffer, offset, size);
|
|
3548
|
+
this.baseOffset = offset;
|
|
3549
|
+
}
|
|
3550
|
+
/**
|
|
3551
|
+
* Get Uint8 at relative offset
|
|
3552
|
+
*/
|
|
3553
|
+
getUint8(offset) {
|
|
3554
|
+
return this.view.getUint8(offset);
|
|
3555
|
+
}
|
|
3556
|
+
/**
|
|
3557
|
+
* Set Uint8 at relative offset
|
|
3558
|
+
*/
|
|
3559
|
+
setUint8(offset, value) {
|
|
3560
|
+
this.view.setUint8(offset, value);
|
|
3561
|
+
}
|
|
3562
|
+
/**
|
|
3563
|
+
* Get Uint32 at relative offset
|
|
3564
|
+
*/
|
|
3565
|
+
getUint32(offset) {
|
|
3566
|
+
return this.view.getUint32(offset, true);
|
|
3567
|
+
}
|
|
3568
|
+
/**
|
|
3569
|
+
* Set Uint32 at relative offset
|
|
3570
|
+
*/
|
|
3571
|
+
setUint32(offset, value) {
|
|
3572
|
+
this.view.setUint32(offset, value, true);
|
|
3573
|
+
}
|
|
3574
|
+
/**
|
|
3575
|
+
* Get BigUint64 at relative offset
|
|
3576
|
+
*/
|
|
3577
|
+
getUint64(offset) {
|
|
3578
|
+
return this.view.getBigUint64(offset, true);
|
|
3579
|
+
}
|
|
3580
|
+
/**
|
|
3581
|
+
* Set BigUint64 at relative offset
|
|
3582
|
+
*/
|
|
3583
|
+
setUint64(offset, value) {
|
|
3584
|
+
this.view.setBigUint64(offset, value, true);
|
|
3585
|
+
}
|
|
3586
|
+
/**
|
|
3587
|
+
* Get bytes at relative offset
|
|
3588
|
+
*/
|
|
3589
|
+
getBytes(offset, length) {
|
|
3590
|
+
return new Uint8Array(this.buffer, this.baseOffset + offset, length);
|
|
3591
|
+
}
|
|
3592
|
+
/**
|
|
3593
|
+
* Set bytes at relative offset
|
|
3594
|
+
*/
|
|
3595
|
+
setBytes(offset, bytes) {
|
|
3596
|
+
this.uint8View.set(bytes, offset);
|
|
3597
|
+
}
|
|
3598
|
+
/**
|
|
3599
|
+
* Get the underlying ArrayBuffer
|
|
3600
|
+
*/
|
|
3601
|
+
getBuffer() {
|
|
3602
|
+
return this.buffer;
|
|
3603
|
+
}
|
|
3604
|
+
/**
|
|
3605
|
+
* Get the base offset
|
|
3606
|
+
*/
|
|
3607
|
+
getBaseOffset() {
|
|
3608
|
+
return this.baseOffset;
|
|
3609
|
+
}
|
|
3610
|
+
};
|
|
3611
|
+
function createBufferPool(config) {
|
|
3612
|
+
const fullConfig = { ...defaultBufferPoolConfig(), ...config };
|
|
3613
|
+
return new BufferPool(fullConfig);
|
|
3614
|
+
}
|
|
3615
|
+
function createZeroCopyBuffer(size) {
|
|
3616
|
+
return new ZeroCopyBuffer(size);
|
|
3617
|
+
}
|
|
3618
|
+
function createSerializer(initialSize) {
|
|
3619
|
+
return new ZeroCopySerializer(initialSize);
|
|
3620
|
+
}
|
|
3621
|
+
function copyBytes(src, dst, dstOffset = 0) {
|
|
3622
|
+
dst.set(src, dstOffset);
|
|
3623
|
+
}
|
|
3624
|
+
function createView(buffer, offset, length) {
|
|
3625
|
+
return new Uint8Array(buffer, offset, length);
|
|
3626
|
+
}
|
|
3627
|
+
|
|
3628
|
+
export {
|
|
3629
|
+
defaultJITConfig,
|
|
3630
|
+
BranchOptimizer,
|
|
3631
|
+
likely,
|
|
3632
|
+
unlikely,
|
|
3633
|
+
LoopOptimizer,
|
|
3634
|
+
CACHE_LINE_SIZE,
|
|
3635
|
+
AlignedBuffer,
|
|
3636
|
+
prefetchHint,
|
|
3637
|
+
ProfileGuidedOptimizer,
|
|
3638
|
+
OptimizedMath,
|
|
3639
|
+
fastInvSqrt,
|
|
3640
|
+
FuncCache,
|
|
3641
|
+
SpinLock,
|
|
3642
|
+
hotPath,
|
|
3643
|
+
coldPath,
|
|
3644
|
+
MemoryOps,
|
|
3645
|
+
detectCPUFeatures,
|
|
3646
|
+
getProfileOptimizer,
|
|
3647
|
+
profile,
|
|
3648
|
+
defaultAffinityConfig,
|
|
3649
|
+
defaultNUMAConfig,
|
|
3650
|
+
CPUAffinity,
|
|
3651
|
+
NUMAOptimizer,
|
|
3652
|
+
CacheOptimizer,
|
|
3653
|
+
HardwareMonitor,
|
|
3654
|
+
createCPUAffinity,
|
|
3655
|
+
createNUMAOptimizer,
|
|
3656
|
+
createCacheOptimizer,
|
|
3657
|
+
createHardwareMonitor,
|
|
3658
|
+
getSystemCPUInfo,
|
|
3659
|
+
getSystemMemoryInfo,
|
|
3660
|
+
IOOperation,
|
|
3661
|
+
defaultIOUringConfig,
|
|
3662
|
+
KernelBypassManager,
|
|
3663
|
+
DirectIOFile,
|
|
3664
|
+
MemoryMappedFile,
|
|
3665
|
+
AsyncSocket,
|
|
3666
|
+
IOBatchProcessor,
|
|
3667
|
+
getKernelBypassManager,
|
|
3668
|
+
defaultTransactionConfig,
|
|
3669
|
+
TransactionBuilder,
|
|
3670
|
+
ComputeBudgetOptimizer,
|
|
3671
|
+
InstructionBatcher,
|
|
3672
|
+
TransactionOptimizer,
|
|
3673
|
+
createTransactionBuilder,
|
|
3674
|
+
createComputeBudgetOptimizer,
|
|
3675
|
+
createInstructionBatcher,
|
|
3676
|
+
createTransactionOptimizer,
|
|
3677
|
+
estimateCompute,
|
|
3678
|
+
calculateOptimalPrice,
|
|
3679
|
+
ThreadPriorityLevel,
|
|
3680
|
+
SchedulerPolicy,
|
|
3681
|
+
defaultRealtimeConfig,
|
|
3682
|
+
ThreadPriority,
|
|
3683
|
+
RealtimeTuner,
|
|
3684
|
+
busyWait,
|
|
3685
|
+
spinLock,
|
|
3686
|
+
LatencyMonitor,
|
|
3687
|
+
PerformanceGovernor,
|
|
3688
|
+
createRealtimeTuner,
|
|
3689
|
+
createThreadPriority,
|
|
3690
|
+
createLatencyMonitor,
|
|
3691
|
+
createPerformanceGovernor,
|
|
3692
|
+
measureTime,
|
|
3693
|
+
createTimer,
|
|
3694
|
+
defaultSIMDConfig,
|
|
3695
|
+
SIMDDetector,
|
|
3696
|
+
VectorizedMath,
|
|
3697
|
+
CryptoSIMD,
|
|
3698
|
+
Float32x4,
|
|
3699
|
+
createSIMDDetector,
|
|
3700
|
+
createVectorizedMath,
|
|
3701
|
+
createCryptoSIMD,
|
|
3702
|
+
isSIMDAvailable,
|
|
3703
|
+
getOptimalSIMDWidth,
|
|
3704
|
+
defaultSyscallBypassConfig,
|
|
3705
|
+
FastTimeProvider,
|
|
3706
|
+
SyscallBypassManager,
|
|
3707
|
+
createSyscallBypassManager,
|
|
3708
|
+
getGlobalTimeProvider,
|
|
3709
|
+
fastNowNs,
|
|
3710
|
+
fastNowUs,
|
|
3711
|
+
fastNowMs,
|
|
3712
|
+
defaultUltraLowLatencyConfig,
|
|
3713
|
+
MemoryPool,
|
|
3714
|
+
LockFreeQueue,
|
|
3715
|
+
MPMCQueue,
|
|
3716
|
+
LatencyOptimizer,
|
|
3717
|
+
prefetch,
|
|
3718
|
+
prefetchArray,
|
|
3719
|
+
createMemoryPool,
|
|
3720
|
+
createLockFreeQueue,
|
|
3721
|
+
createMPMCQueue,
|
|
3722
|
+
busySpin,
|
|
3723
|
+
yieldToEventLoop,
|
|
3724
|
+
defaultBufferPoolConfig,
|
|
3725
|
+
ZeroCopyBuffer,
|
|
3726
|
+
BufferPool,
|
|
3727
|
+
ZeroCopySerializer,
|
|
3728
|
+
FixedBufferView,
|
|
3729
|
+
createBufferPool,
|
|
3730
|
+
createZeroCopyBuffer,
|
|
3731
|
+
createSerializer,
|
|
3732
|
+
copyBytes,
|
|
3733
|
+
createView,
|
|
3734
|
+
perf_exports
|
|
3735
|
+
};
|