Skip to content

Commit

Permalink
add randomness workload to sui-benchmark (MystenLabs#18758)
Browse files Browse the repository at this point in the history
  • Loading branch information
aschran authored Jul 22, 2024
1 parent ff941c1 commit ef4639c
Show file tree
Hide file tree
Showing 6 changed files with 257 additions and 2 deletions.
5 changes: 4 additions & 1 deletion crates/sui-benchmark/src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,9 +175,12 @@ pub enum RunSpec {
// relative weight of adversarial transactions in the benchmark workload
#[clap(long, num_args(1..), value_delimiter = ',', default_values_t = [0])]
adversarial: Vec<u32>,
// relative weight of adversarial transactions in the benchmark workload
// relative weight of shared deletion transactions in the benchmark workload
#[clap(long, num_args(1..), value_delimiter = ',', default_values_t = [0])]
shared_deletion: Vec<u32>,
// relative weight of randomness transactions in the benchmark workload
#[clap(long, num_args(1..), value_delimiter = ',', default_values_t = [0])]
randomness: Vec<u32>,

// --- workload-specific options --- (TODO: use subcommands or similar)
// 100 for max hotness i.e all requests target
Expand Down
1 change: 1 addition & 0 deletions crates/sui-benchmark/src/workloads/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ pub mod adversarial;
pub mod batch_payment;
pub mod delegation;
pub mod payload;
pub mod randomness;
pub mod shared_counter;
pub mod shared_object_deletion;
pub mod transfer_object;
Expand Down
215 changes: 215 additions & 0 deletions crates/sui-benchmark/src/workloads/randomness.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,215 @@
// Copyright (c) Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

use crate::drivers::Interval;
use crate::system_state_observer::SystemStateObserver;
use crate::util::publish_basics_package;
use crate::workloads::payload::Payload;
use crate::workloads::workload::{
Workload, WorkloadBuilder, ESTIMATED_COMPUTATION_COST, MAX_GAS_FOR_TESTING,
};
use crate::workloads::GasCoinConfig;
use crate::workloads::{Gas, WorkloadBuilderInfo, WorkloadParams};
use crate::{ExecutionEffects, ValidatorProxy};
use async_trait::async_trait;
use std::sync::Arc;
use sui_test_transaction_builder::TestTransactionBuilder;
use sui_types::crypto::get_key_pair;
use sui_types::object::Owner;
use sui_types::SUI_RANDOMNESS_STATE_OBJECT_ID;
use sui_types::{
base_types::{ObjectID, SequenceNumber},
transaction::Transaction,
};
use tracing::{error, info};

/// The max amount of gas units needed for a payload.
pub const MAX_GAS_IN_UNIT: u64 = 1_000_000_000;

#[derive(Debug)]
pub struct RandomnessTestPayload {
package_id: ObjectID,
randomness_initial_shared_version: SequenceNumber,
gas: Gas,
system_state_observer: Arc<SystemStateObserver>,
}

impl std::fmt::Display for RandomnessTestPayload {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "randomness")
}
}

impl Payload for RandomnessTestPayload {
fn make_new_payload(&mut self, effects: &ExecutionEffects) {
if !effects.is_ok() {
effects.print_gas_summary();
error!("Randomness tx failed... Status: {:?}", effects.status());
}
self.gas.0 = effects.gas_object().0;
}
fn make_transaction(&mut self) -> Transaction {
let rgp = self
.system_state_observer
.state
.borrow()
.reference_gas_price;
TestTransactionBuilder::new(self.gas.1, self.gas.0, rgp)
.call_emit_random(self.package_id, self.randomness_initial_shared_version)
.build_and_sign(self.gas.2.as_ref())
}
}

#[derive(Debug)]
pub struct RandomnessWorkloadBuilder {
num_payloads: u64,
rgp: u64,
}

impl RandomnessWorkloadBuilder {
pub fn from(
workload_weight: f32,
target_qps: u64,
num_workers: u64,
in_flight_ratio: u64,
reference_gas_price: u64,
duration: Interval,
group: u32,
) -> Option<WorkloadBuilderInfo> {
let target_qps = (workload_weight * target_qps as f32) as u64;
let num_workers = (workload_weight * num_workers as f32).ceil() as u64;
let max_ops = target_qps * in_flight_ratio;
if max_ops == 0 || num_workers == 0 {
None
} else {
let workload_params = WorkloadParams {
group,
target_qps,
num_workers,
max_ops,
duration,
};
let workload_builder = Box::<dyn WorkloadBuilder<dyn Payload>>::from(Box::new(
RandomnessWorkloadBuilder {
num_payloads: max_ops,
rgp: reference_gas_price,
},
));
let builder_info = WorkloadBuilderInfo {
workload_params,
workload_builder,
};
Some(builder_info)
}
}
}

#[async_trait]
impl WorkloadBuilder<dyn Payload> for RandomnessWorkloadBuilder {
async fn generate_coin_config_for_init(&self) -> Vec<GasCoinConfig> {
let (address, keypair) = get_key_pair();
vec![GasCoinConfig {
amount: MAX_GAS_FOR_TESTING,
address,
keypair: Arc::new(keypair),
}]
}
async fn generate_coin_config_for_payloads(&self) -> Vec<GasCoinConfig> {
let mut configs = vec![];
let amount = MAX_GAS_IN_UNIT * self.rgp + ESTIMATED_COMPUTATION_COST;
// Gas coins for running workload
for _i in 0..self.num_payloads {
let (address, keypair) = get_key_pair();
configs.push(GasCoinConfig {
amount,
address,
keypair: Arc::new(keypair),
});
}
configs
}
async fn build(
&self,
init_gas: Vec<Gas>,
payload_gas: Vec<Gas>,
) -> Box<dyn Workload<dyn Payload>> {
Box::<dyn Workload<dyn Payload>>::from(Box::new(RandomnessWorkload {
basics_package_id: None,
randomness_initial_shared_version: None,
init_gas,
payload_gas,
}))
}
}

#[derive(Debug)]
pub struct RandomnessWorkload {
pub basics_package_id: Option<ObjectID>,
pub randomness_initial_shared_version: Option<SequenceNumber>,
pub init_gas: Vec<Gas>,
pub payload_gas: Vec<Gas>,
}

#[async_trait]
impl Workload<dyn Payload> for RandomnessWorkload {
async fn init(
&mut self,
proxy: Arc<dyn ValidatorProxy + Sync + Send>,
system_state_observer: Arc<SystemStateObserver>,
) {
if self.basics_package_id.is_some() {
return;
}
let gas_price = system_state_observer.state.borrow().reference_gas_price;
let gas = self
.init_gas
.first()
.expect("Not enough gas to initialize randomness workload");

// Publish basics package
if self.basics_package_id.is_none() {
info!("Publishing basics package");
self.basics_package_id = Some(
publish_basics_package(gas.0, proxy.clone(), gas.1, &gas.2, gas_price)
.await
.0,
);
info!("Basics package id {:?}", self.basics_package_id);
}

// Get randomness shared object initial version
if self.randomness_initial_shared_version.is_none() {
let obj = proxy
.get_object(SUI_RANDOMNESS_STATE_OBJECT_ID)
.await
.expect("Failed to get randomness object");
let Owner::Shared {
initial_shared_version,
} = obj.owner()
else {
panic!("randomness object must be shared");
};
self.randomness_initial_shared_version = Some(*initial_shared_version);
}
}
async fn make_test_payloads(
&self,
_proxy: Arc<dyn ValidatorProxy + Sync + Send>,
system_state_observer: Arc<SystemStateObserver>,
) -> Vec<Box<dyn Payload>> {
let mut shared_payloads = vec![];
for g in self.payload_gas.iter() {
shared_payloads.push(Box::new(RandomnessTestPayload {
package_id: self.basics_package_id.unwrap(),
randomness_initial_shared_version: self.randomness_initial_shared_version.unwrap(),
gas: g.clone(),
system_state_observer: system_state_observer.clone(),
}));
}
let payloads: Vec<Box<dyn Payload>> = shared_payloads
.into_iter()
.map(|b| Box::<dyn Payload>::from(b))
.collect();
payloads
}
}
17 changes: 16 additions & 1 deletion crates/sui-benchmark/src/workloads/workload_configuration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use std::sync::Arc;
use tracing::info;

use super::adversarial::{AdversarialPayloadCfg, AdversarialWorkloadBuilder};
use super::randomness::RandomnessWorkloadBuilder;
use super::shared_object_deletion::SharedCounterDeletionWorkloadBuilder;

pub struct WorkloadConfiguration;
Expand All @@ -39,6 +40,7 @@ impl WorkloadConfiguration {
delegation,
batch_payment,
adversarial,
randomness,
shared_counter_hotness_factor,
num_shared_counters,
shared_counter_max_tip,
Expand Down Expand Up @@ -69,6 +71,7 @@ impl WorkloadConfiguration {
shared_deletion[i],
adversarial[i],
AdversarialPayloadCfg::from_str(&adversarial_cfg[i]).unwrap(),
randomness[i],
batch_payment_size[i],
shared_counter_hotness_factor[i],
num_shared_counters.as_ref().map(|n| n[i]),
Expand Down Expand Up @@ -146,6 +149,7 @@ impl WorkloadConfiguration {
shared_deletion_weight: u32,
adversarial_weight: u32,
adversarial_cfg: AdversarialPayloadCfg,
randomness_weight: u32,
batch_payment_size: u32,
shared_counter_hotness_factor: u32,
num_shared_counters: Option<u64>,
Expand All @@ -160,7 +164,8 @@ impl WorkloadConfiguration {
+ transfer_object_weight
+ delegation_weight
+ batch_payment_weight
+ adversarial_weight;
+ adversarial_weight
+ randomness_weight;
let reference_gas_price = system_state_observer.state.borrow().reference_gas_price;
let mut workload_builders = vec![];
let shared_workload = SharedCounterWorkloadBuilder::from(
Expand Down Expand Up @@ -227,6 +232,16 @@ impl WorkloadConfiguration {
workload_group,
);
workload_builders.push(adversarial_workload);
let randomness_workload = RandomnessWorkloadBuilder::from(
randomness_weight as f32 / total_weight as f32,
target_qps,
num_workers,
in_flight_ratio,
reference_gas_price,
duration,
workload_group,
);
workload_builders.push(randomness_workload);

workload_builders
}
Expand Down
4 changes: 4 additions & 0 deletions crates/sui-benchmark/tests/simtest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -811,6 +811,7 @@ mod test {
batch_payment_weight: u32,
shared_deletion_weight: u32,
shared_counter_hotness_factor: u32,
randomness_weight: u32,
num_shared_counters: Option<u64>,
use_shared_counter_max_tip: bool,
shared_counter_max_tip: u64,
Expand All @@ -826,6 +827,7 @@ mod test {
batch_payment_weight: 1,
shared_deletion_weight: 1,
shared_counter_hotness_factor: 50,
randomness_weight: 1,
num_shared_counters: Some(1),
use_shared_counter_max_tip: false,
shared_counter_max_tip: 0,
Expand Down Expand Up @@ -886,6 +888,7 @@ mod test {
let delegation_weight = config.delegation_weight;
let batch_payment_weight = config.batch_payment_weight;
let shared_object_deletion_weight = config.shared_deletion_weight;
let randomness_weight = config.randomness_weight;

// Run random payloads at 100% load
let adversarial_cfg = AdversarialPayloadCfg::from_str("0-1.0").unwrap();
Expand Down Expand Up @@ -916,6 +919,7 @@ mod test {
shared_object_deletion_weight,
adversarial_weight,
adversarial_cfg,
randomness_weight,
batch_payment_size,
shared_counter_hotness_factor,
num_shared_counters,
Expand Down
17 changes: 17 additions & 0 deletions crates/sui-test-transaction-builder/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,23 @@ impl TestTransactionBuilder {
)
}

pub fn call_emit_random(
self,
package_id: ObjectID,
randomness_initial_shared_version: SequenceNumber,
) -> Self {
self.move_call(
package_id,
"random",
"new",
vec![CallArg::Object(ObjectArg::SharedObject {
id: SUI_RANDOMNESS_STATE_OBJECT_ID,
initial_shared_version: randomness_initial_shared_version,
mutable: false,
})],
)
}

pub fn call_request_add_validator(self) -> Self {
self.move_call(
SUI_SYSTEM_PACKAGE_ID,
Expand Down

0 comments on commit ef4639c

Please sign in to comment.