Skip to content

Commit a2ff563

Browse files
authored
Nour/cu profiling (#1870)
* add CU profiling test * reduce CUs for target base
1 parent 7d4a635 commit a2ff563

File tree

6 files changed

+819
-75
lines changed

6 files changed

+819
-75
lines changed

programs/drift/src/instructions/lp_pool.rs

Lines changed: 16 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,10 @@ use super::optional_accounts::{get_whitelist_token, load_maps, AccountMaps};
5151
use crate::controller::spot_balance::update_spot_market_cumulative_interest;
5252
use crate::controller::token::{receive, send_from_program_vault_with_signature_seeds};
5353
use crate::instructions::constraints::*;
54-
use crate::state::lp_pool::{CONSTITUENT_PDA_SEED, LP_POOL_TOKEN_VAULT_PDA_SEED};
54+
use crate::state::lp_pool::{
55+
AmmInventoryAndPrices, ConstituentIndexAndDecimalAndPrice, CONSTITUENT_PDA_SEED,
56+
LP_POOL_TOKEN_VAULT_PDA_SEED,
57+
};
5558

5659
pub fn handle_update_constituent_target_base<'c: 'info, 'info>(
5760
ctx: Context<'_, '_, 'c, 'info, UpdateConstituentTargetBase<'info>>,
@@ -68,7 +71,6 @@ pub fn handle_update_constituent_target_base<'c: 'info, 'info>(
6871
amm_cache.check_oracle_staleness(slot, MAX_AMM_CACHE_ORACLE_STALENESS_FOR_TARGET_CALC)?;
6972
amm_cache.check_perp_market_staleness(slot, MAX_AMM_CACHE_STALENESS_FOR_TARGET_CALC)?;
7073

71-
let state = &ctx.accounts.state;
7274
let mut constituent_target_base: AccountZeroCopyMut<
7375
'_,
7476
TargetsDatum,
@@ -81,13 +83,6 @@ pub fn handle_update_constituent_target_base<'c: 'info, 'info>(
8183
"Constituent target base lp pool pubkey does not match lp pool pubkey",
8284
)?;
8385

84-
let num_constituents = constituent_target_base.len();
85-
for datum in constituent_target_base.iter() {
86-
msg!("weight datum: {:?}", datum);
87-
}
88-
89-
let slot = Clock::get()?.slot;
90-
9186
let amm_constituent_mapping: AccountZeroCopy<
9287
'_,
9388
AmmConstituentDatum,
@@ -103,7 +98,7 @@ pub fn handle_update_constituent_target_base<'c: 'info, 'info>(
10398
let constituent_map =
10499
ConstituentMap::load(&ConstituentSet::new(), &lp_pool_key, remaining_accounts)?;
105100

106-
let mut amm_inventories: Vec<(u16, i64, i64)> =
101+
let mut amm_inventories: Vec<AmmInventoryAndPrices> =
107102
Vec::with_capacity(amm_constituent_mapping.len() as usize);
108103
for (_, datum) in amm_constituent_mapping.iter().enumerate() {
109104
let cache_info = amm_cache.get(datum.perp_market_index as u32);
@@ -117,39 +112,29 @@ pub fn handle_update_constituent_target_base<'c: 'info, 'info>(
117112
continue;
118113
}
119114

120-
amm_inventories.push((
121-
datum.perp_market_index,
122-
cache_info.position,
123-
cache_info.oracle_price,
124-
));
115+
amm_inventories.push(AmmInventoryAndPrices {
116+
perp_market_index: datum.perp_market_index,
117+
inventory: cache_info.position,
118+
price: cache_info.oracle_price,
119+
});
125120
}
126121

127122
if amm_inventories.is_empty() {
128123
msg!("No valid inventories found for constituent target weights update");
129124
return Ok(());
130125
}
131126

132-
let mut constituent_indexes_and_decimals_and_prices: Vec<(u16, u8, i64)> =
127+
let mut constituent_indexes_and_decimals_and_prices: Vec<ConstituentIndexAndDecimalAndPrice> =
133128
Vec::with_capacity(constituent_map.0.len());
134129
for (index, loader) in &constituent_map.0 {
135130
let constituent_ref = loader.load()?;
136-
constituent_indexes_and_decimals_and_prices.push((
137-
*index,
138-
constituent_ref.decimals,
139-
constituent_ref.last_oracle_price,
140-
));
131+
constituent_indexes_and_decimals_and_prices.push(ConstituentIndexAndDecimalAndPrice {
132+
constituent_index: *index,
133+
decimals: constituent_ref.decimals,
134+
price: constituent_ref.last_oracle_price,
135+
});
141136
}
142137

143-
let exists_invalid_constituent_index = constituent_indexes_and_decimals_and_prices
144-
.iter()
145-
.any(|(index, _, _)| *index as u32 >= num_constituents);
146-
147-
validate!(
148-
!exists_invalid_constituent_index,
149-
ErrorCode::InvalidUpdateConstituentTargetBaseArgument,
150-
"Constituent index larger than numr of constituent target weights"
151-
)?;
152-
153138
constituent_target_base.update_target_base(
154139
&amm_constituent_mapping,
155140
amm_inventories.as_slice(),

programs/drift/src/state/lp_pool.rs

Lines changed: 58 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1154,46 +1154,84 @@ pub fn calculate_target_weight(
11541154
}
11551155

11561156
/// Update target base based on amm_inventory and mapping
1157+
pub struct AmmInventoryAndPrices {
1158+
pub perp_market_index: u16,
1159+
pub inventory: i64,
1160+
pub price: i64,
1161+
}
1162+
1163+
pub struct ConstituentIndexAndDecimalAndPrice {
1164+
pub constituent_index: u16,
1165+
pub decimals: u8,
1166+
pub price: i64,
1167+
}
1168+
11571169
impl<'a> AccountZeroCopyMut<'a, TargetsDatum, ConstituentTargetBaseFixed> {
11581170
pub fn update_target_base(
11591171
&mut self,
11601172
mapping: &AccountZeroCopy<'a, AmmConstituentDatum, AmmConstituentMappingFixed>,
11611173
// (perp market index, inventory, price)
1162-
amm_inventory_and_prices: &[(u16, i64, i64)],
1163-
constituents_indexes_and_decimals_and_prices: &[(u16, u8, i64)],
1174+
amm_inventory_and_prices: &[AmmInventoryAndPrices],
1175+
constituents_indexes_and_decimals_and_prices: &[ConstituentIndexAndDecimalAndPrice],
11641176
slot: u64,
11651177
) -> DriftResult<Vec<i128>> {
1178+
// Precompute notional by perp market index
1179+
let mut notional_by_perp: Vec<(u16, i128)> =
1180+
Vec::with_capacity(amm_inventory_and_prices.len());
1181+
for &AmmInventoryAndPrices {
1182+
perp_market_index,
1183+
inventory,
1184+
price,
1185+
} in amm_inventory_and_prices.iter()
1186+
{
1187+
let notional = (inventory as i128)
1188+
.safe_mul(price as i128)?
1189+
.safe_div(BASE_PRECISION_I128)?;
1190+
notional_by_perp.push((perp_market_index, notional));
1191+
}
1192+
notional_by_perp.sort_by_key(|&(idx, _)| idx);
1193+
1194+
#[inline]
1195+
fn find_notional(sorted: &[(u16, i128)], idx: u16) -> Option<i128> {
1196+
match sorted.binary_search_by_key(&idx, |&(p, _)| p) {
1197+
Ok(i) => Some(sorted[i].1),
1198+
Err(_) => None,
1199+
}
1200+
}
1201+
11661202
let mut results = Vec::with_capacity(constituents_indexes_and_decimals_and_prices.len());
1167-
for (i, (constituent_index, decimals, price)) in
1168-
constituents_indexes_and_decimals_and_prices
1169-
.iter()
1170-
.enumerate()
1203+
for (
1204+
i,
1205+
&ConstituentIndexAndDecimalAndPrice {
1206+
constituent_index,
1207+
decimals,
1208+
price,
1209+
},
1210+
) in constituents_indexes_and_decimals_and_prices
1211+
.iter()
1212+
.enumerate()
11711213
{
11721214
let mut target_notional = 0i128;
11731215

1174-
for (perp_market_index, inventory, price) in amm_inventory_and_prices.iter() {
1175-
if let Some(idx) = mapping.iter().position(|d| {
1176-
&d.perp_market_index == perp_market_index
1177-
&& d.constituent_index == *constituent_index
1178-
}) {
1179-
let weight = mapping.get(idx as u32).weight; // PERCENTAGE_PRECISION
1180-
1181-
let notional: i128 = (*inventory as i128)
1182-
.safe_mul(*price as i128)?
1183-
.safe_div(BASE_PRECISION_I128)?;
1216+
for d in mapping.iter() {
1217+
if d.constituent_index != constituent_index {
1218+
continue;
1219+
}
11841220

1221+
if let Some(perp_notional) = find_notional(&notional_by_perp, d.perp_market_index) {
1222+
let w = d.weight as i128;
11851223
target_notional = target_notional.saturating_add(
1186-
notional
1187-
.saturating_mul(weight as i128)
1224+
perp_notional
1225+
.saturating_mul(w)
11881226
.saturating_div(PERCENTAGE_PRECISION_I128),
11891227
);
11901228
}
11911229
}
11921230

11931231
let cell = self.get_mut(i as u32);
11941232
let target_base = target_notional
1195-
.safe_mul(10_i128.pow(*decimals as u32))?
1196-
.safe_div(*price as i128)?
1233+
.safe_mul(10_i128.pow(decimals as u32))?
1234+
.safe_div(price as i128)?
11971235
* -1; // Want to target opposite sign of total scaled notional inventory
11981236

11991237
msg!(

programs/drift/src/state/lp_pool/tests.rs

Lines changed: 93 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -68,17 +68,49 @@ mod tests {
6868
}
6969
};
7070

71-
let amm_inventory_and_price: Vec<(u16, i64, i64)> = vec![
72-
(0, 4 * BASE_PRECISION_I64, 100_000 * PRICE_PRECISION_I64), // $400k BTC
73-
(1, 2000 * BASE_PRECISION_I64, 200 * PRICE_PRECISION_I64), // $400k SOL
74-
(2, 200 * BASE_PRECISION_I64, 1500 * PRICE_PRECISION_I64), // $300k ETH
75-
(3, 16500 * BASE_PRECISION_I64, PRICE_PRECISION_I64), // $16.5k FARTCOIN
71+
let amm_inventory_and_price: Vec<AmmInventoryAndPrices> = vec![
72+
AmmInventoryAndPrices {
73+
perp_market_index: 0,
74+
inventory: 4 * BASE_PRECISION_I64,
75+
price: 100_000 * PRICE_PRECISION_I64,
76+
}, // $400k BTC
77+
AmmInventoryAndPrices {
78+
perp_market_index: 1,
79+
inventory: 2000 * BASE_PRECISION_I64,
80+
price: 200 * PRICE_PRECISION_I64,
81+
}, // $400k SOL
82+
AmmInventoryAndPrices {
83+
perp_market_index: 2,
84+
inventory: 200 * BASE_PRECISION_I64,
85+
price: 1500 * PRICE_PRECISION_I64,
86+
}, // $300k ETH
87+
AmmInventoryAndPrices {
88+
perp_market_index: 3,
89+
inventory: 16500 * BASE_PRECISION_I64,
90+
price: PRICE_PRECISION_I64,
91+
}, // $16.5k FARTCOIN
7692
];
7793
let constituents_indexes_and_decimals_and_prices = vec![
78-
(0, 6, 100_000 * PRICE_PRECISION_I64),
79-
(1, 6, 200 * PRICE_PRECISION_I64),
80-
(2, 6, 1500 * PRICE_PRECISION_I64),
81-
(3, 6, PRICE_PRECISION_I64), // USDC
94+
ConstituentIndexAndDecimalAndPrice {
95+
constituent_index: 0,
96+
decimals: 6,
97+
price: 100_000 * PRICE_PRECISION_I64,
98+
},
99+
ConstituentIndexAndDecimalAndPrice {
100+
constituent_index: 1,
101+
decimals: 6,
102+
price: 200 * PRICE_PRECISION_I64,
103+
},
104+
ConstituentIndexAndDecimalAndPrice {
105+
constituent_index: 2,
106+
decimals: 6,
107+
price: 1500 * PRICE_PRECISION_I64,
108+
},
109+
ConstituentIndexAndDecimalAndPrice {
110+
constituent_index: 3,
111+
decimals: 6,
112+
price: PRICE_PRECISION_I64,
113+
}, // USDC
82114
];
83115
let aum = 2_000_000 * QUOTE_PRECISION; // $2M AUM
84116

@@ -112,7 +144,7 @@ mod tests {
112144
calculate_target_weight(
113145
base.cast::<i64>().unwrap(),
114146
&SpotMarket::default_quote_market(),
115-
amm_inventory_and_price.get(index).unwrap().2,
147+
amm_inventory_and_price.get(index).unwrap().price,
116148
aum,
117149
)
118150
.unwrap()
@@ -155,8 +187,17 @@ mod tests {
155187
}
156188
};
157189

158-
let amm_inventory_and_prices: Vec<(u16, i64, i64)> = vec![(0, 1_000_000, 1_000_000)];
159-
let constituents_indexes_and_decimals_and_prices = vec![(1, 6, 1_000_000)];
190+
let amm_inventory_and_prices: Vec<AmmInventoryAndPrices> = vec![AmmInventoryAndPrices {
191+
perp_market_index: 0,
192+
inventory: 1_000_000,
193+
price: 1_000_000,
194+
}];
195+
let constituents_indexes_and_decimals_and_prices =
196+
vec![ConstituentIndexAndDecimalAndPrice {
197+
constituent_index: 1,
198+
decimals: 6,
199+
price: 1_000_000,
200+
}];
160201
let aum = 1_000_000;
161202
let now_ts = 1000;
162203

@@ -215,8 +256,17 @@ mod tests {
215256
};
216257

217258
let price = PRICE_PRECISION_I64;
218-
let amm_inventory_and_prices: Vec<(u16, i64, i64)> = vec![(0, BASE_PRECISION_I64, price)];
219-
let constituents_indexes_and_decimals_and_prices = vec![(1, 6, price)];
259+
let amm_inventory_and_prices: Vec<AmmInventoryAndPrices> = vec![AmmInventoryAndPrices {
260+
perp_market_index: 0,
261+
inventory: BASE_PRECISION_I64,
262+
price,
263+
}];
264+
let constituents_indexes_and_decimals_and_prices =
265+
vec![ConstituentIndexAndDecimalAndPrice {
266+
constituent_index: 1,
267+
decimals: 6,
268+
price,
269+
}];
220270
let aum = 1_000_000;
221271
let now_ts = 1234;
222272

@@ -293,9 +343,23 @@ mod tests {
293343
}
294344
};
295345

296-
let amm_inventory_and_prices: Vec<(u16, i64, i64)> = vec![(0, 1_000_000_000, 1_000_000)];
297-
let constituents_indexes_and_decimals_and_prices =
298-
vec![(1, 6, 1_000_000), (2, 6, 1_000_000)];
346+
let amm_inventory_and_prices: Vec<AmmInventoryAndPrices> = vec![AmmInventoryAndPrices {
347+
perp_market_index: 0,
348+
inventory: 1_000_000_000,
349+
price: 1_000_000,
350+
}];
351+
let constituents_indexes_and_decimals_and_prices = vec![
352+
ConstituentIndexAndDecimalAndPrice {
353+
constituent_index: 1,
354+
decimals: 6,
355+
price: 1_000_000,
356+
},
357+
ConstituentIndexAndDecimalAndPrice {
358+
constituent_index: 2,
359+
decimals: 6,
360+
price: 1_000_000,
361+
},
362+
];
299363

300364
let aum = 1_000_000;
301365
let now_ts = 999;
@@ -330,7 +394,7 @@ mod tests {
330394
constituents_indexes_and_decimals_and_prices
331395
.get(i as usize)
332396
.unwrap()
333-
.2,
397+
.price,
334398
aum,
335399
)
336400
.unwrap(),
@@ -368,8 +432,17 @@ mod tests {
368432
}
369433
};
370434

371-
let amm_inventory_and_prices: Vec<(u16, i64, i64)> = vec![(0, 1_000_000, 142_000_000)];
372-
let constituents_indexes_and_decimals_and_prices = vec![(1, 6, 142_000_000)];
435+
let amm_inventory_and_prices: Vec<AmmInventoryAndPrices> = vec![AmmInventoryAndPrices {
436+
perp_market_index: 0,
437+
inventory: 1_000_000,
438+
price: 142_000_000,
439+
}];
440+
let constituents_indexes_and_decimals_and_prices =
441+
vec![ConstituentIndexAndDecimalAndPrice {
442+
constituent_index: 1,
443+
decimals: 6,
444+
price: 142_000_000,
445+
}];
373446

374447
let prices = vec![142_000_000];
375448
let aum = 0;

sdk/src/driftClient.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10352,9 +10352,7 @@ export class DriftClient {
1035210352
public async getUpdateConstituentOracleInfoIx(
1035310353
constituent: ConstituentAccount
1035410354
): Promise<TransactionInstruction> {
10355-
const spotMarket = await this.getSpotMarketAccount(
10356-
constituent.spotMarketIndex
10357-
);
10355+
const spotMarket = this.getSpotMarketAccount(constituent.spotMarketIndex);
1035810356
return this.program.instruction.updateConstituentOracleInfo({
1035910357
accounts: {
1036010358
keeper: this.wallet.publicKey,

tests/lpPool.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import {
1212
Transaction,
1313
} from '@solana/web3.js';
1414
import {
15-
createAssociatedTokenAccountIdempotentInstruction,
1615
createAssociatedTokenAccountInstruction,
1716
createInitializeMint2Instruction,
1817
createMintToInstruction,

0 commit comments

Comments
 (0)