Skip to content

Commit 0d07b9a

Browse files
feat: implement a new type FifoMap and associated tests (#318)
Co-authored-by: MicaiahReid <[email protected]>
1 parent 5c22a14 commit 0d07b9a

File tree

5 files changed

+263
-33
lines changed

5 files changed

+263
-33
lines changed

crates/cli/src/cli/mod.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -197,15 +197,19 @@ pub struct StartSimnet {
197197
/// Start surfpool without a remote RPC client to simulate an offline environment (eg. surfpool start --offline)
198198
#[clap(long = "offline", action=ArgAction::SetTrue, default_value = "false")]
199199
pub offline: bool,
200-
/// Disable instruction profiling (default: false)
200+
/// Disable instruction profiling (eg. surfpool start --disable-instruction-profiling)
201201
#[clap(long = "disable-instruction-profiling", action=ArgAction::SetTrue)]
202202
pub disable_instruction_profiling: bool,
203-
/// The log level to use for simnet logs. Options are "trace", "debug", "info", "warn", "error".
203+
/// The log level to use for simnet logs. Options are "trace", "debug", "info", "warn", "error". (eg. surfpool start --log-level debug)
204204
#[arg(long = "log-level", short = 'l', default_value = "info")]
205205
pub log_level: String,
206-
/// The directory to put simnet logs.
206+
/// The directory to put simnet logs. (eg. surfpool start --log-path ./logs)
207207
#[arg(long = "log-path", default_value = DEFAULT_LOG_DIR.as_str())]
208208
pub log_dir: String,
209+
/// The maximum number of transaction profiles to hold in memory.
210+
/// Changing this will affect the memory usage of surfpool. (eg. surfpool start --max-profiles 2000)
211+
#[arg(long = "max-profiles", short = 'c', default_value = "200")]
212+
pub max_profiles: usize,
209213
}
210214

211215
#[derive(clap::ValueEnum, PartialEq, Clone, Debug)]
@@ -325,6 +329,7 @@ impl StartSimnet {
325329
expiry: None,
326330
offline_mode: self.offline,
327331
instruction_profiling_enabled: !self.disable_instruction_profiling,
332+
max_profiles: self.max_profiles,
328333
}
329334
}
330335

crates/core/src/error.rs

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -424,16 +424,6 @@ impl SurfpoolError {
424424
Self(error)
425425
}
426426

427-
pub fn transaction_not_found_in_svm<S>(signature: S) -> Self
428-
where
429-
S: Display,
430-
{
431-
let mut error = Error::internal_error();
432-
error.message =
433-
format!("Transaction with signature '{signature}' was not found in the SVM");
434-
Self(error)
435-
}
436-
437427
pub fn tag_not_found(tag: &str) -> Self {
438428
let mut error = Error::internal_error();
439429
error.message = format!("Profile result associated with tag '{tag}' not found in the SVM");

crates/core/src/surfnet/locker.rs

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -744,6 +744,10 @@ impl SurfnetSvmLocker {
744744
self.with_svm_reader(|svm_reader| svm_reader.instruction_profiling_enabled)
745745
}
746746

747+
pub fn get_profiling_map_capacity(&self) -> usize {
748+
self.with_svm_reader(|svm_reader| svm_reader.max_profiles)
749+
}
750+
747751
pub async fn process_transaction(
748752
&self,
749753
remote_ctx: &Option<(SurfnetRemoteClient, CommitmentConfig)>,
@@ -2327,22 +2331,10 @@ impl SurfnetSvmLocker {
23272331
config: &RpcProfileResultConfig,
23282332
) -> SurfpoolResult<Option<UiKeyedProfileResult>> {
23292333
let result = match &signature_or_uuid {
2330-
UuidOrSignature::Signature(signature) => {
2331-
let profile = self.with_svm_reader(|svm| {
2332-
svm.executed_transaction_profiles.get(signature).cloned()
2333-
});
2334-
let transaction_exists =
2335-
self.with_svm_reader(|svm| svm.transactions.contains_key(signature));
2336-
if profile.is_none() && transaction_exists {
2337-
return Err(SurfpoolError::transaction_not_found_in_svm(signature));
2338-
} else {
2339-
profile
2340-
}
2341-
}
2334+
UuidOrSignature::Signature(signature) => self
2335+
.with_svm_reader(|svm| svm.executed_transaction_profiles.get(signature).cloned()),
23422336
UuidOrSignature::Uuid(uuid) => {
2343-
let profile = self
2344-
.with_svm_reader(|svm| svm.simulated_transaction_profiles.get(uuid).cloned());
2345-
profile
2337+
self.with_svm_reader(|svm| svm.simulated_transaction_profiles.get(uuid).cloned())
23462338
}
23472339
};
23482340
Ok(result.map(|profile| self.encode_ui_keyed_profile_result(profile, config)))

crates/core/src/surfnet/svm.rs

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use std::{
2+
cmp::max,
23
collections::{BinaryHeap, HashMap, HashSet, VecDeque},
34
str::FromStr,
45
};
@@ -46,9 +47,10 @@ use spl_token_2022::extension::{
4647
scaled_ui_amount::ScaledUiAmountConfig,
4748
};
4849
use surfpool_types::{
49-
AccountChange, AccountProfileState, DEFAULT_SLOT_TIME_MS, Idl, ProfileResult, RpcProfileDepth,
50-
RpcProfileResultConfig, SimnetEvent, TransactionConfirmationStatus, TransactionStatusEvent,
51-
UiAccountChange, UiAccountProfileState, UiProfileResult, VersionedIdl,
50+
AccountChange, AccountProfileState, DEFAULT_PROFILING_MAP_CAPACITY, DEFAULT_SLOT_TIME_MS,
51+
FifoMap, Idl, ProfileResult, RpcProfileDepth, RpcProfileResultConfig, SimnetEvent,
52+
TransactionConfirmationStatus, TransactionStatusEvent, UiAccountChange, UiAccountProfileState,
53+
UiProfileResult, VersionedIdl,
5254
types::{
5355
ComputeUnitsEstimationResult, KeyedProfileResult, UiKeyedProfileResult, UuidOrSignature,
5456
},
@@ -112,7 +114,7 @@ pub struct SurfnetSvm {
112114
pub slot_subscriptions: Vec<Sender<SlotInfo>>,
113115
pub profile_tag_map: HashMap<String, Vec<UuidOrSignature>>,
114116
pub simulated_transaction_profiles: HashMap<Uuid, KeyedProfileResult>,
115-
pub executed_transaction_profiles: HashMap<Signature, KeyedProfileResult>,
117+
pub executed_transaction_profiles: FifoMap<Signature, KeyedProfileResult>,
116118
pub logs_subscriptions: Vec<LogsSubscriptionData>,
117119
pub updated_at: u64,
118120
pub slot_time: u64,
@@ -136,6 +138,7 @@ pub struct SurfnetSvm {
136138
pub registered_idls: HashMap<Pubkey, BinaryHeap<VersionedIdl>>,
137139
pub feature_set: FeatureSet,
138140
pub instruction_profiling_enabled: bool,
141+
pub max_profiles: usize,
139142
}
140143

141144
pub const FEATURE: Feature = Feature {
@@ -186,7 +189,7 @@ impl SurfnetSvm {
186189
slot_subscriptions: Vec::new(),
187190
profile_tag_map: HashMap::new(),
188191
simulated_transaction_profiles: HashMap::new(),
189-
executed_transaction_profiles: HashMap::new(),
192+
executed_transaction_profiles: FifoMap::default(),
190193
logs_subscriptions: Vec::new(),
191194
updated_at: Utc::now().timestamp_millis() as u64,
192195
slot_time: DEFAULT_SLOT_TIME_MS,
@@ -207,6 +210,7 @@ impl SurfnetSvm {
207210
registered_idls: HashMap::new(),
208211
feature_set,
209212
instruction_profiling_enabled: true,
213+
max_profiles: DEFAULT_PROFILING_MAP_CAPACITY,
210214
};
211215

212216
// Generate the initial synthetic blockhash
@@ -240,6 +244,7 @@ impl SurfnetSvm {
240244
self.updated_at = Utc::now().timestamp_millis() as u64;
241245
self.slot_time = slot_time;
242246
self.instruction_profiling_enabled = do_profile_instructions;
247+
self.set_profiling_map_capacity(self.max_profiles);
243248

244249
if let Some(remote_client) = remote_ctx {
245250
let _ = self
@@ -265,6 +270,12 @@ impl SurfnetSvm {
265270
self.instruction_profiling_enabled = do_profile_instructions;
266271
}
267272

273+
pub fn set_profiling_map_capacity(&mut self, capacity: usize) {
274+
let clamped_capacity = max(1, capacity);
275+
self.max_profiles = clamped_capacity;
276+
self.executed_transaction_profiles = FifoMap::new(clamped_capacity);
277+
}
278+
268279
/// Airdrops a specified amount of lamports to a single public key.
269280
///
270281
/// # Arguments
@@ -2345,4 +2356,20 @@ mod tests {
23452356
assert_eq!(ui_account, expected_account);
23462357
}
23472358
}
2359+
2360+
#[test]
2361+
fn test_profiling_map_capacity_default() {
2362+
let (svm, _events_rx, _geyser_rx) = SurfnetSvm::new();
2363+
assert_eq!(
2364+
svm.executed_transaction_profiles.capacity(),
2365+
DEFAULT_PROFILING_MAP_CAPACITY
2366+
);
2367+
}
2368+
2369+
#[test]
2370+
fn test_profiling_map_capacity_set() {
2371+
let (mut svm, _events_rx, _geyser_rx) = SurfnetSvm::new();
2372+
svm.set_profiling_map_capacity(10);
2373+
assert_eq!(svm.executed_transaction_profiles.capacity(), 10);
2374+
}
23482375
}

0 commit comments

Comments
 (0)