From 7570f3179cbd70d278d70c98ab8a9f1baeb4fb13 Mon Sep 17 00:00:00 2001 From: Zhang Zhuo Date: Sun, 20 Jun 2021 18:05:07 +0800 Subject: [PATCH] feat: add new order in trade msg (#189) * feat: add order in trade msg * feat: add global string intern pool * fix * lint --- Cargo.lock | 1 + Cargo.toml | 1 + src/matchengine/market/mod.rs | 11 ++++++++++- src/matchengine/market/order.rs | 26 +++++++++----------------- src/matchengine/market/trade.rs | 5 +++++ src/matchengine/sequencer.rs | 13 +++++++++++++ src/message/mod.rs | 2 +- src/utils/mod.rs | 2 ++ src/utils/strings.rs | 14 ++++++++++++++ 9 files changed, 56 insertions(+), 19 deletions(-) create mode 100644 src/utils/strings.rs diff --git a/Cargo.lock b/Cargo.lock index 730efa25..8932f961 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -614,6 +614,7 @@ dependencies = [ "humantime-serde", "hyper", "itertools 0.10.0", + "lazy_static", "log", "nix", "num_enum", diff --git a/Cargo.toml b/Cargo.toml index aec9aad4..1d38a940 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,6 +20,7 @@ futures-util = { version = "0.3.13", default-features = false } humantime-serde = "1.0.1" hyper = "0.14.4" itertools = "0.10.0" +lazy_static = "1.4.0" log = "0.4.14" nix = "0.20.0" num_enum = "0.5.1" diff --git a/src/matchengine/market/mod.rs b/src/matchengine/market/mod.rs index d6e492a3..1196583e 100644 --- a/src/matchengine/market/mod.rs +++ b/src/matchengine/market/mod.rs @@ -344,6 +344,9 @@ impl Market { bid_order_id: bid_order.id, bid_role: if taker_is_ask { MarketRole::MAKER } else { MarketRole::TAKER }, bid_fee, + + ask_order: None, + bid_order: None, #[cfg(feature = "emit_state_diff")] state_before: Default::default(), #[cfg(feature = "emit_state_diff")] @@ -355,6 +358,10 @@ impl Market { if self.disable_self_trade { debug_assert_ne!(trade.ask_user_id, trade.bid_user_id); } + let ask_order_is_new = ask_order.finished_base.is_zero(); + let ask_order_before = *ask_order; + let bid_order_is_new = bid_order.finished_base.is_zero(); + let bid_order_before = *bid_order; ask_order.remain -= traded_base_amount; bid_order.remain -= traded_base_amount; ask_order.finished_base += traded_base_amount; @@ -412,6 +419,8 @@ impl Market { state_after, #[cfg(feature = "emit_state_diff")] state_before, + ask_order: if ask_order_is_new { Some(ask_order_before) } else { None }, + bid_order: if bid_order_is_new { Some(bid_order_before) } else { None }, ..trade }; persistor.put_trade(&trade); @@ -420,7 +429,7 @@ impl Market { let maker_finished = maker.remain.is_zero(); if maker_finished { - finished_orders.push(maker.clone()); + finished_orders.push(*maker); } else { // When maker_finished, `order_finish` will send message. // So we don't need to send the finish message here. diff --git a/src/matchengine/market/order.rs b/src/matchengine/market/order.rs index 221f10cb..24b3ebaa 100644 --- a/src/matchengine/market/order.rs +++ b/src/matchengine/market/order.rs @@ -1,4 +1,5 @@ use crate::types::{OrderSide, OrderType}; +use crate::utils::intern_string; use rust_decimal::Decimal; use serde::{Deserialize, Serialize}; use std::cmp::Ordering; @@ -73,45 +74,36 @@ impl PartialOrd for MarketKeyBid { } } -#[derive(Debug, Clone)] -pub enum MarketString { - Left(&'static str), - Right(String), -} +#[derive(Debug, Clone, Copy)] +pub struct MarketString(&'static str); impl From<&'static str> for MarketString { fn from(str: &'static str) -> Self { - MarketString::Left(str) + MarketString(str) } } impl std::ops::Deref for MarketString { type Target = str; fn deref(&self) -> &Self::Target { - match self { - MarketString::Left(str) => *str, - MarketString::Right(stri) => stri.as_str(), - } + self.0 } } impl serde::ser::Serialize for MarketString { fn serialize(&self, serializer: S) -> Result { - match self { - MarketString::Left(str) => serializer.serialize_str(*str), - MarketString::Right(stri) => serializer.serialize_str(stri.as_str()), - } + serializer.serialize_str(self.0) } } impl<'de> serde::de::Deserialize<'de> for MarketString { fn deserialize>(deserializer: D) -> Result { let s = String::deserialize(deserializer)?; - Ok(MarketString::Right(s)) + Ok(intern_string(&s).into()) } } -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, Copy)] pub struct Order { pub id: u64, pub base: MarketString, @@ -181,6 +173,6 @@ impl OrderRc { } pub(super) fn deep(&self) -> Order { - self.borrow().clone() + *self.borrow() } } diff --git a/src/matchengine/market/trade.rs b/src/matchengine/market/trade.rs index 3cc0db83..7eb9a7b2 100644 --- a/src/matchengine/market/trade.rs +++ b/src/matchengine/market/trade.rs @@ -1,3 +1,4 @@ +use crate::market::Order; use crate::types::MarketRole; use rust_decimal::Decimal; use serde::{Deserialize, Serialize}; @@ -47,6 +48,10 @@ pub struct Trade { pub bid_role: MarketRole, pub bid_fee: Decimal, + // only not none when this is this order's first trade + pub ask_order: Option, + pub bid_order: Option, + #[cfg(feature = "emit_state_diff")] pub state_before: VerboseTradeState, #[cfg(feature = "emit_state_diff")] diff --git a/src/matchengine/sequencer.rs b/src/matchengine/sequencer.rs index 864752cf..a331566a 100644 --- a/src/matchengine/sequencer.rs +++ b/src/matchengine/sequencer.rs @@ -2,6 +2,7 @@ pub struct Sequencer { order_id: u64, trade_id: u64, + msg_id: u64, operation_log_id: u64, } @@ -10,6 +11,7 @@ impl Sequencer { self.set_operation_log_id(0); self.set_order_id(0); self.set_trade_id(0); + self.set_msg_id(0); } pub fn next_order_id(&mut self) -> u64 { self.order_id += 1; @@ -24,6 +26,10 @@ impl Sequencer { self.operation_log_id += 1; self.operation_log_id } + pub fn next_msg_id(&mut self) -> u64 { + self.msg_id += 1; + self.msg_id + } pub fn get_operation_log_id(&self) -> u64 { self.operation_log_id } @@ -33,6 +39,9 @@ impl Sequencer { pub fn get_order_id(&self) -> u64 { self.order_id } + pub fn get_msg_id(&self) -> u64 { + self.msg_id + } pub fn set_operation_log_id(&mut self, id: u64) { log::debug!("set operation_log id {}", id); self.operation_log_id = id; @@ -45,4 +54,8 @@ impl Sequencer { log::debug!("set order id {}", id); self.order_id = id; } + pub fn set_msg_id(&mut self, id: u64) { + log::debug!("set msg id {}", id); + self.msg_id = id; + } } diff --git a/src/message/mod.rs b/src/message/mod.rs index 63aee416..869ca91f 100644 --- a/src/message/mod.rs +++ b/src/message/mod.rs @@ -87,7 +87,7 @@ impl OrderMessage { pub fn from_order(order: &Order, at_step: OrderEventType) -> Self { Self { event: at_step, - order: order.clone(), + order: *order, base: order.base.to_string(), quote: order.quote.to_string(), } diff --git a/src/utils/mod.rs b/src/utils/mod.rs index b2adc7f7..9e3577cb 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -1,2 +1,4 @@ pub mod timeutil; pub use timeutil::*; +pub mod strings; +pub use strings::*; diff --git a/src/utils/strings.rs b/src/utils/strings.rs new file mode 100644 index 00000000..c4bf40fc --- /dev/null +++ b/src/utils/strings.rs @@ -0,0 +1,14 @@ +use lazy_static::lazy_static; +use std::collections::HashMap; +use std::sync::Mutex; +lazy_static! { + pub static ref STRING_POOL: Mutex> = Default::default(); +} + +pub fn intern_string(s: &str) -> &'static str { + *STRING_POOL + .lock() + .unwrap() + .entry(s.to_owned()) + .or_insert_with(|| Box::leak(s.to_string().into_boxed_str())) +}