serum health: use lower-precision division (#750)
This saves around 1/3rd of the compute for active serum markets.
This commit is contained in:
parent
20eb02af01
commit
dfde7ec43f
|
@ -19,6 +19,7 @@ use anchor_lang::prelude::*;
|
||||||
use fixed::types::I80F48;
|
use fixed::types::I80F48;
|
||||||
|
|
||||||
use crate::error::*;
|
use crate::error::*;
|
||||||
|
use crate::i80f48::LowPrecisionDivision;
|
||||||
use crate::serum3_cpi::{OpenOrdersAmounts, OpenOrdersSlim};
|
use crate::serum3_cpi::{OpenOrdersAmounts, OpenOrdersSlim};
|
||||||
use crate::state::{
|
use crate::state::{
|
||||||
Bank, MangoAccountRef, PerpMarket, PerpMarketIndex, PerpPosition, Serum3MarketIndex,
|
Bank, MangoAccountRef, PerpMarket, PerpMarketIndex, PerpPosition, Serum3MarketIndex,
|
||||||
|
@ -293,8 +294,9 @@ impl Serum3Info {
|
||||||
) -> I80F48 {
|
) -> I80F48 {
|
||||||
let quote_asset = quote_info.prices.asset(health_type);
|
let quote_asset = quote_info.prices.asset(health_type);
|
||||||
let base_liab = base_info.prices.liab(health_type);
|
let base_liab = base_info.prices.liab(health_type);
|
||||||
// OPTIMIZATION: These divisions can be extremely expensive (up to 5k CU each)
|
let reserved_quote_as_base_oracle = (self.reserved_quote * quote_asset)
|
||||||
let reserved_quote_as_base_oracle = self.reserved_quote * quote_asset / base_liab;
|
.checked_div_f64_precision(base_liab)
|
||||||
|
.unwrap();
|
||||||
if self.reserved_quote_as_base_highest_bid != 0 {
|
if self.reserved_quote_as_base_highest_bid != 0 {
|
||||||
self.reserved_base
|
self.reserved_base
|
||||||
+ reserved_quote_as_base_oracle.min(self.reserved_quote_as_base_highest_bid)
|
+ reserved_quote_as_base_oracle.min(self.reserved_quote_as_base_highest_bid)
|
||||||
|
@ -312,8 +314,9 @@ impl Serum3Info {
|
||||||
) -> I80F48 {
|
) -> I80F48 {
|
||||||
let base_asset = base_info.prices.asset(health_type);
|
let base_asset = base_info.prices.asset(health_type);
|
||||||
let quote_liab = quote_info.prices.liab(health_type);
|
let quote_liab = quote_info.prices.liab(health_type);
|
||||||
// OPTIMIZATION: These divisions can be extremely expensive (up to 5k CU each)
|
let reserved_base_as_quote_oracle = (self.reserved_base * base_asset)
|
||||||
let reserved_base_as_quote_oracle = self.reserved_base * base_asset / quote_liab;
|
.checked_div_f64_precision(quote_liab)
|
||||||
|
.unwrap();
|
||||||
if self.reserved_base_as_quote_lowest_ask != 0 {
|
if self.reserved_base_as_quote_lowest_ask != 0 {
|
||||||
self.reserved_quote
|
self.reserved_quote
|
||||||
+ reserved_base_as_quote_oracle.min(self.reserved_base_as_quote_lowest_ask)
|
+ reserved_base_as_quote_oracle.min(self.reserved_base_as_quote_lowest_ask)
|
||||||
|
|
|
@ -77,7 +77,7 @@ async fn test_health_compute_tokens() -> Result<(), TransportError> {
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_health_compute_serum() -> Result<(), TransportError> {
|
async fn test_health_compute_serum() -> Result<(), TransportError> {
|
||||||
let mut test_builder = TestContextBuilder::new();
|
let mut test_builder = TestContextBuilder::new();
|
||||||
test_builder.test().set_compute_max_units(150_000);
|
test_builder.test().set_compute_max_units(130_000);
|
||||||
let context = test_builder.start_default().await;
|
let context = test_builder.start_default().await;
|
||||||
let solana = &context.solana.clone();
|
let solana = &context.solana.clone();
|
||||||
|
|
||||||
|
@ -244,7 +244,7 @@ async fn test_health_compute_serum() -> Result<(), TransportError> {
|
||||||
let avg_cu_increase = cu_measurements.windows(2).map(|p| p[1] - p[0]).sum::<u64>()
|
let avg_cu_increase = cu_measurements.windows(2).map(|p| p[1] - p[0]).sum::<u64>()
|
||||||
/ (cu_measurements.len() - 1) as u64;
|
/ (cu_measurements.len() - 1) as u64;
|
||||||
println!("average cu increase: {avg_cu_increase}");
|
println!("average cu increase: {avg_cu_increase}");
|
||||||
assert!(avg_cu_increase < 10000);
|
assert!(avg_cu_increase < 7000);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue