1.3.0 ให้ทุก process ของ SDK แชร์สิ่งที่เรียนรู้ผ่าน Redis — pool ไหนไม่มี, pool ไหนว่างเปล่า, token มีกี่ทศนิยม — process ใหม่จึงเริ่มด้วยความรู้ของทุกคนก่อนหน้า ผล: call ลดอีก 25–30 % บน HyperEVM ตั้งแต่ quote แรก, request บน BNB ลด 20 % ราคาเท่าเดิม 0.00 bps ทั้ง 18 กรณี
Round 1 stopped asking about pools that do not exist. Round 2 adds two things: the SDK now notices pools that exist but are empty (a quarter of what was left on HyperEVM) and skips them for an hour, and every SDK process publishes what it learned to a shared Redis so the next process, on any machine, starts warm. Measured with the same A/B protocol against the frozen 1.2.0 build. Δ price 0.00 bps on all 18 cases.
| chain · pair | requests | inner calls | bytes | Δ price |
|---|---|---|---|---|
| HyperEVM · HYPE → USDT0 | 2 → 2 | 432 → 321 (−26 %) | −26 % | 0.00 bps |
| HyperEVM · USDT0 → WHYPE | 2 → 2 | 401 → 297 (−26 %) | −26 % | 0.00 bps |
| HyperEVM · kHYPE → USDT0 | 3 → 2 (−33 %) | 568 → 396 (−30 %) | −31 % | 0.00 bps |
| BNB · BNB → USDT | 5 → 4 (−20 %) | 1,351 → 1,190 (−12 %) | −17 % | 0.00 bps |
| BNB · BUSD → USDT | 5 → 4 (−20 %) | 1,351 → 1,190 (−12 %) | −17 % | 0.00 bps |
| BNB · ETH → CAKE | 5 → 4 (−20 %) | 1,351 → 1,190 (−12 %) | −17 % | 0.00 bps |
Same route chosen in every case. The first case of each run carries the one-time Redis connect + sync (~1.2 s), which shows up as +14–18 % wall time on that case only; every later quote is 4–31 % faster than 1.2.0.
Before designing the feature we measured the Redis instance from the SDK's point of view:
| operation | measured | consequence |
|---|---|---|
| connect | 651 ms | paid once per process; started in the constructor so the first quote rarely waits the full amount |
PING round trip | 332 ms | a quote must never wait on Redis → sync once at start (bounded 2 s), then every 30 s in the background |
300 KB SET + GET | 3,037 ms | slower than fetching the same pool state from the RPC (≈1.0 s) → pool state is not shared; only skip-lists and decimals (a few KB) |
MORO_SHARED_CACHE_REDIS_URL on the server (or sharedCache.redisUrl), the cache is off otherwise, and the leaked credential must be rotated. A malicious write could hide live pools (worse prices; never a wrong swap, because the router still enforces minAmountOut). Before publishing: rotate it, give the SDK a read-only ACL user, and write only from trusted servers or a small proxy.sharedCache.httpUrl) brings the same −25 % to the web app; that is the next step.{ sharedCache: false }.# warm the shared cache from one process, then A/B a fresh process against the frozen 1.2.0 build
npx ts-node -T -O '{"module":"commonjs"}' benchmark/quote-quality.ts --chain hyperevm
npx ts-node -T -O '{"module":"commonjs"}' benchmark/ab-test.ts --chain hyperevm --a v1.2.0 --b dist --runs 2 --pause 15000
npx ts-node -T -O '{"module":"commonjs"}' benchmark/ab-test.ts --chain bsc --a v1.2.0 --b dist --runs 2
Write-up: benchmark/rounds/2.md; raw samples: benchmark/results/2026-09-13-07-0*-round2-v1.3.0.json; code: src/services/sharedCache.ts — on korrio/moro-sdk-optimized. The npm package stays at 1.1.0 until the team publishes.