Skip to content

Modernize deps & optimize matching engine performance#401

Open
lispc wants to merge 18 commits into
masterfrom
modernize-deps
Open

Modernize deps & optimize matching engine performance#401
lispc wants to merge 18 commits into
masterfrom
modernize-deps

Conversation

@lispc

@lispc lispc commented Jun 6, 2026

Copy link
Copy Markdown
Member

Summary

This PR modernizes multiple parts of the codebase and adds a round of matching-engine performance optimizations.

Modernization Changes

  • Auto-generate gRPC code via tonic-build in build.rs instead of hand-copied src/rpc/exchange/ and src/rpc/rollup/
  • Replace BaseProducer manual thread with FutureProducer + tokio::sync::mpsc channel
  • Simplify message/ trait hierarchy: replaced RdConsumerExt, MessageHandlerAsync, TypedMessageHandlerAsync, TypedMessageHandler, SyncTyped, Simple, TopicBuilder, ChainedTopicBuilder with a clean MessageHandler trait + TypedHandler/SimpleHandler
  • Remove fluidex-common git dependency entirely; inline crypto traits (FrExt, DecimalExt, PubkeyExt, SignatureExt) into src/utils/crypto.rs
  • Add direct deps: babyjubjub-rs, ff_ce, poseidon-rs, num-bigint, num-traits
  • Update GitHub Actions CI:
    • Rust: 1.53.0 → 1.90.0
    • actions: checkout@v2 → v4, action-rs → dtolnay/rust-toolchain, cache@v2 → Swatinem/rust-cache@v2
    • Node.js: 16 → 20
    • docker-compose path: orchestra/dockerdocker/
    • Install protobuf-compiler for tonic-build

Performance Optimizations

Profiling under pair-trade load revealed the engine was bottlenecked by Kafka producer backpressure and JSON serialization.

  • Kafka producer channel capacity: 100K → 1M to avoid try_send().unwrap() panic under load
  • Trade struct: market/base/quote from String to InternedString, eliminating per-trade heap allocations
  • Kafka message serialization: replace serde_json::to_string with simd_json::to_string
  • BalanceMapKey: asset from String to InternedString; hash on the interned pointer for O(1) HashMap lookups
  • InternedString: add From<&str>, PartialEq, Eq, and Hash impls needed by the new callers

Known Limitations / Notes

  • The matching engine core remains single-threaded (all writes route through one mpsc consumer). The measured single-market throughput ceiling is ~10K orders/s with the current client setup.
  • simd-json is used only for Kafka producer serialization, not for REST/gRPC payloads, so downstream JSON consumers remain compatible.
  • CI is currently pinned to Rust 1.90.0 because that was the latest stable at the time the modernization started.

@lispc lispc force-pushed the modernize-deps branch from 3592c90 to b879109 Compare June 6, 2026 08:56
lispc added 16 commits June 6, 2026 17:17
Also make persist internals pub(crate) for unit tests
…ly signature, market order adaptive check, longer persistor wait)
- Fix tests/trade.ts import path ./fluidex -> ../fluidex
- Fix all new e2e tests initAccounts to register users sequentially
  (server overrides user_id to last_user_id+1)
- Fix balance_consistency.ts precision test: server rounds, not rejects
- Fix state_recovery.ts debugReset test: verify clean state after hard reset
- Includes docker-compose.yaml inline fix (remove orchestra submodule dep)
This makes the matching engine usable as a standalone library
without any zk-specific dependencies.

Key changes:
- New  module with trait abstractions:
  - : pluggable order signature verification
  - : pluggable order commitment builder
  -  implementations for non-zk deployments
  -  implementations (BabyJubJub + Poseidon) for zk-rollup
- :  feature gates babyjubjub-rs, poseidon-rs, ff
- : module hidden behind  feature
- : removed hard-coded
- :  uses injected trait objects
- :
  -  now accepts  +
  -  changed to
- : removed  (moved to )
- : removed  (moved to )
- : selects auth impl based on  feature

Non-zk build:
Zk build:      (default features include zk-rollup)

All 40 unit tests pass in both configurations.
Clippy clean in both configurations.
Non-zk deployments are now the default.  To build with zk support:

    cargo build --features zk-rollup

All Rust unit tests (40/40) and JS e2e tests pass in both modes.
…nge/action

Regression introduced in cf5651b where URL paths were accidentally
reverted from the d2afd93 refactor. Fixes CI integration-test failures
in print_orders.ts due to 404 errors on /restapi/* endpoints.
Prevents syntax error 'limit' that caused /internal_txs endpoint
to return empty results, breaking transfer.ts integration tests.
- Fix CI workflow names (all were 'CI') and update branch protection
  rules to remove stale '1.56.0' suffix from required status checks
- Update docs (testing.md, AGENTS.md, README.md):
  - Correct perftest CLI params (--requests, --duration-secs)
  - Document pair-trade sustainability (periodic cancelAll + role swap)
  - Add Node.js vs Rust perf comparison (~100x gap)
  - Add macOS advisory lock workaround note
- Rewrite stress.ts: dual-user, periodic cancel, total balance check
- Add perf_test.ts: 50-user mixed-load stress test
- perftest.rs: add periodic cancelAll + role swap for sustainable pair-trade
- persistor.rs: use dedicated PgConnection for migration (macOS advisory lock fix)
- dto.rs: downgrade empty signature log from warn to debug
…lanceMapKey hashing

- Kafka producer channel capacity 100K -> 1M (avoid panic under load)
- Trade market/base/quote: String -> InternedString
- Replace serde_json with simd-json for Kafka message serialization
- BalanceMapKey.asset: String -> InternedString with pointer-based Hash
- InternedString: add From<&str>, Eq, Hash impls
@lispc lispc changed the title Modernize: tonic-build, FutureProducer, simplify message traits, remove fluidex-common, update CI Modernize deps & optimize matching engine performance Jun 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant