mirror of
https://github.com/PR0M3TH3AN/TORCH.git
synced 2026-10-27 07:51:52 +00:00
perf: optimize rankRelays for subset queries
- Optimized `RelayHealthManager.rankRelays` to use O(M log M) lookup for small subsets instead of O(N) filter. - Added `byRelay` Map to `_sortedCache` for O(1) access. - Fixed `NaN` bug in `buildRelayHealthConfig` when `minActiveRelayPool` is undefined. - Updated `perf/benchmark-lock-ops.mjs` to measure subset performance. - Added performance report `reports/performance/weekly-perf-report-2026-02-18.md`. - Achieved ~6.8x speedup in benchmark. Co-authored-by: PR0M3TH3AN <[email protected]>
This commit is contained in:
1 parent
d290bf684d
commit
6614535361
5 files changed
+2707
-7
No files matched your search
@@ -5,7 +5,7 @@ const healthManager = new RelayHealthManager();
|
||||
|
||||
// Setup mock relays
|
||||
const relays = [];
|
||||
for (let i = 0; i < 100; i++) {
|
||||
for (let i = 0; i < 1000; i++) {
|
||||
relays.push(`wss://relay-${i}.example.com`);
|
||||
}
|
||||
|
||||
@@ -26,16 +26,20 @@ for (const relay of relays) {
|
||||
}
|
||||
}
|
||||
|
||||
// Benchmark rankRelays
|
||||
// Ensure all are cached
|
||||
healthManager.rankRelays(relays, config);
|
||||
|
||||
// Benchmark rankRelays with a small subset
|
||||
const start = performance.now();
|
||||
const iterations = 10000;
|
||||
const subset = relays.slice(0, 5); // Requesting only 5 relays out of 1000
|
||||
|
||||
for (let i = 0; i < iterations; i++) {
|
||||
healthManager.rankRelays(relays, config);
|
||||
healthManager.rankRelays(subset, config);
|
||||
}
|
||||
|
||||
const end = performance.now();
|
||||
const duration = end - start;
|
||||
|
||||
console.log(`RankRelays x ${iterations}: ${duration.toFixed(2)}ms`);
|
||||
console.log(`RankRelays (Subset 5/1000) x ${iterations}: ${duration.toFixed(2)}ms`);
|
||||
console.log(`Average per call: ${(duration / iterations).toFixed(4)}ms`);
|
||||
@@ -0,0 +1,21 @@
|
||||
# Weekly Performance Report: 2026-02-18
|
||||
|
||||
## System Info
|
||||
Linux devbox 6.8.0 #1 SMP PREEMPT_DYNAMIC Wed Jan 14 23:11:35 UTC 2026 x86_64 x86_64 x86_64 GNU/Linux
|
||||
v22.22.0
|
||||
|
||||
## Baseline: Lock Ops
|
||||
```
|
||||
RankRelays x 10000: 209.17ms
|
||||
Average per call: 0.0209ms
|
||||
```
|
||||
## Baseline: Lock Ops (Subset 5/1000)
|
||||
```
|
||||
RankRelays (Subset 5/1000) x 10000: 237.77ms
|
||||
Average per call: 0.0238ms
|
||||
```
|
||||
## After: Lock Ops
|
||||
```
|
||||
RankRelays (Subset 5/1000) x 10000: 34.78ms
|
||||
Average per call: 0.0035ms
|
||||
```
|
||||
+35
-3
@@ -285,7 +285,7 @@ export class RelayHealthManager {
|
||||
}
|
||||
|
||||
// Sort by score (desc), then quarantine status, then latency (asc), then name
|
||||
entries.sort((a, b) => {
|
||||
const comparator = (a, b) => {
|
||||
if (b.score !== a.score) return b.score - a.score;
|
||||
if (a.summary.quarantined !== b.summary.quarantined) return a.summary.quarantined ? 1 : -1;
|
||||
if (a.summary.averageLatencyMs !== b.summary.averageLatencyMs) {
|
||||
@@ -294,15 +294,47 @@ export class RelayHealthManager {
|
||||
return a.summary.averageLatencyMs - b.summary.averageLatencyMs;
|
||||
}
|
||||
return a.relay.localeCompare(b.relay);
|
||||
});
|
||||
};
|
||||
entries.sort(comparator);
|
||||
|
||||
this._sortedCache = {
|
||||
version: this._metricsVersion,
|
||||
validUntil: minQuarantineUntil,
|
||||
entries,
|
||||
byRelay: new Map(entries.map((e) => [e.relay, e])),
|
||||
comparator,
|
||||
};
|
||||
}
|
||||
|
||||
// Optimization: if requesting a small subset of total known relays,
|
||||
// look them up directly instead of filtering the entire list.
|
||||
// Threshold: if requested set is smaller than 50% of cached entries.
|
||||
if (relays.length > 0 && relays.length * 2 < this._sortedCache.entries.length) {
|
||||
const subset = [];
|
||||
for (const relay of relays) {
|
||||
const entry = this._sortedCache.byRelay.get(relay);
|
||||
if (entry) {
|
||||
subset.push(entry);
|
||||
}
|
||||
}
|
||||
// Re-sort the subset to maintain ranking order
|
||||
subset.sort(this._sortedCache.comparator);
|
||||
|
||||
return subset.map((entry) => {
|
||||
const quarantineRemainingMs = entry.metrics.quarantineUntil > nowMs
|
||||
? entry.metrics.quarantineUntil - nowMs
|
||||
: 0;
|
||||
return {
|
||||
relay: entry.relay,
|
||||
score: entry.score,
|
||||
summary: {
|
||||
...entry.summary,
|
||||
quarantineRemainingMs,
|
||||
},
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
const requestedSet = new Set(relays);
|
||||
return this._sortedCache.entries
|
||||
.filter((entry) => requestedSet.has(entry.relay))
|
||||
@@ -425,7 +457,7 @@ function buildRelayHealthConfig(deps) {
|
||||
quarantineCooldownMs: deps.quarantineCooldownMs ?? DEFAULT_QUARANTINE_COOLDOWN_MS,
|
||||
maxQuarantineCooldownMs: deps.maxQuarantineCooldownMs ?? DEFAULT_MAX_QUARANTINE_COOLDOWN_MS,
|
||||
snapshotIntervalMs: deps.snapshotIntervalMs ?? DEFAULT_SNAPSHOT_INTERVAL_MS,
|
||||
minActiveRelayPool: Math.max(1, deps.minActiveRelayPool),
|
||||
minActiveRelayPool: Math.max(1, deps.minActiveRelayPool ?? 1),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
# Task Log
|
||||
Completed successfully.
|
||||
+2641
File diff suppressed because it is too large.
Load diff
Reference in new issue
Block a user