Skip to content

Commit fd7c7cc

Browse files
committed
Renamed perf structures; cleaned up perf traces; added initial storage performance tests
1 parent 9e603ac commit fd7c7cc

File tree

7 files changed

+183
-33
lines changed

7 files changed

+183
-33
lines changed

sdk/core/azure_core_test/src/perf/config_tests.rs

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,11 @@ fn create_failed_test(_runner: &PerfRunner) -> CreatePerfTestReturn {
2020
}
2121

2222
// Helper function to create a basic test metadata for testing
23-
fn create_basic_test_metadata() -> TestMetadata {
24-
TestMetadata {
23+
fn create_basic_test_metadata() -> PerfTestMetadata {
24+
PerfTestMetadata {
2525
name: "basic_test",
2626
description: "A basic test for testing purposes",
27-
options: vec![TestOption {
27+
options: vec![PerfTestOption {
2828
name: "test-option",
2929
short_activator: 't',
3030
long_activator: "test-option",
@@ -38,12 +38,12 @@ fn create_basic_test_metadata() -> TestMetadata {
3838
}
3939

4040
// Helper function to create test metadata with multiple options
41-
fn create_complex_test_metadata() -> TestMetadata {
42-
TestMetadata {
41+
fn create_complex_test_metadata() -> PerfTestMetadata {
42+
PerfTestMetadata {
4343
name: "complex_test",
4444
description: "A complex test with multiple options",
4545
options: vec![
46-
TestOption {
46+
PerfTestOption {
4747
name: "mandatory-option",
4848
short_activator: 'm',
4949
long_activator: "mandatory",
@@ -52,7 +52,7 @@ fn create_complex_test_metadata() -> TestMetadata {
5252
mandatory: true,
5353
sensitive: false,
5454
},
55-
TestOption {
55+
PerfTestOption {
5656
name: "sensitive-option",
5757
short_activator: 's',
5858
long_activator: "sensitive",
@@ -61,7 +61,7 @@ fn create_complex_test_metadata() -> TestMetadata {
6161
mandatory: false,
6262
sensitive: true,
6363
},
64-
TestOption {
64+
PerfTestOption {
6565
name: "flag-option",
6666
short_activator: 'f',
6767
long_activator: "flag",
@@ -74,11 +74,11 @@ fn create_complex_test_metadata() -> TestMetadata {
7474
}
7575

7676
// Helper function to create test metadata without short activators
77-
fn create_no_short_activator_test_metadata() -> TestMetadata {
78-
TestMetadata {
77+
fn create_no_short_activator_test_metadata() -> PerfTestMetadata {
78+
PerfTestMetadata {
7979
name: "no_short_test",
8080
description: "Test without short activators",
81-
options: vec![TestOption {
81+
options: vec![PerfTestOption {
8282
name: "long-only",
8383
short_activator: '\0',
8484
long_activator: "long-only",
@@ -494,7 +494,7 @@ fn test_perf_runner_options_debug() {
494494

495495
#[test]
496496
fn test_test_option_debug_and_default() {
497-
let option = TestOption::default();
497+
let option = PerfTestOption::default();
498498

499499
// Test default values
500500
assert_eq!(option.name, "");
@@ -592,11 +592,11 @@ fn complex_test_create(_runner: &PerfRunner) -> CreatePerfTestReturn {
592592

593593
#[tokio::test]
594594
async fn test_perf_runner_with_test_functions() {
595-
let tests = vec![TestMetadata {
595+
let tests = vec![PerfTestMetadata {
596596
name: "complex_test",
597597
description: "A complex test with multiple options",
598598
options: vec![
599-
TestOption {
599+
PerfTestOption {
600600
name: "mandatory-option",
601601
short_activator: 'm',
602602
long_activator: "mandatory",
@@ -605,7 +605,7 @@ async fn test_perf_runner_with_test_functions() {
605605
mandatory: true,
606606
sensitive: false,
607607
},
608-
TestOption {
608+
PerfTestOption {
609609
name: "sensitive-option",
610610
short_activator: 's',
611611
long_activator: "sensitive",
@@ -614,7 +614,7 @@ async fn test_perf_runner_with_test_functions() {
614614
mandatory: false,
615615
sensitive: true,
616616
},
617-
TestOption {
617+
PerfTestOption {
618618
name: "flag-option",
619619
short_activator: 'f',
620620
long_activator: "flag",

sdk/core/azure_core_test/src/perf/framework_tests.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,10 +91,10 @@ async fn test_perf_runner_with_single_test() {
9191
let runner = PerfRunner::with_command_line(
9292
env!("CARGO_MANIFEST_DIR"),
9393
file!(),
94-
vec![TestMetadata {
94+
vec![PerfTestMetadata {
9595
name: "fibonacci1",
9696
description: "A basic test for testing purposes",
97-
options: vec![TestOption {
97+
options: vec![PerfTestOption {
9898
name: "count",
9999
mandatory: true,
100100
short_activator: 'c',

sdk/core/azure_core_test/src/perf/mod.rs

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -30,21 +30,21 @@ pub type CreatePerfTestReturn =
3030

3131
/// Metadata about a performance test.
3232
#[derive(Debug, Clone)]
33-
pub struct TestMetadata {
33+
pub struct PerfTestMetadata {
3434
/// The name of the test suite.
3535
pub name: &'static str,
3636
/// A brief description of the test suite.
3737
pub description: &'static str,
3838
/// The set of test options supported by this test.
39-
pub options: Vec<TestOption>,
39+
pub options: Vec<PerfTestOption>,
4040

4141
/// A function used to create the performance test.
4242
pub create_test: fn(&PerfRunner) -> CreatePerfTestReturn,
4343
}
4444

4545
/// #A `TestOptions` defines a set of options for the test which will be merged with the common test inputs to define the command line for the performance test.
4646
#[derive(Debug, Default, Clone)]
47-
pub struct TestOption {
47+
pub struct PerfTestOption {
4848
/// The name of the test option. This is used as the key in the `TestArguments` map.
4949
pub name: &'static str,
5050

@@ -112,7 +112,7 @@ impl From<&ArgMatches> for PerfRunnerOptions {
112112
#[derive(Debug, Clone)]
113113
pub struct PerfRunner {
114114
options: PerfRunnerOptions,
115-
tests: Vec<TestMetadata>,
115+
tests: Vec<PerfTestMetadata>,
116116
arguments: ArgMatches,
117117
package_dir: &'static str,
118118
module_name: &'static str,
@@ -123,7 +123,7 @@ impl PerfRunner {
123123
pub fn new(
124124
package_dir: &'static str,
125125
module_name: &'static str,
126-
tests: Vec<TestMetadata>,
126+
tests: Vec<PerfTestMetadata>,
127127
) -> azure_core::Result<Self> {
128128
let command = Self::get_command_from_metadata(&tests);
129129
let arguments = command.get_matches();
@@ -141,7 +141,7 @@ impl PerfRunner {
141141
pub fn with_command_line(
142142
package_dir: &'static str,
143143
module_name: &'static str,
144-
tests: Vec<TestMetadata>,
144+
tests: Vec<PerfTestMetadata>,
145145
args: Vec<&str>,
146146
) -> azure_core::Result<Self> {
147147
let command = Self::get_command_from_metadata(&tests);
@@ -273,6 +273,7 @@ impl PerfRunner {
273273
_test_name: &str,
274274
duration: Duration,
275275
) -> azure_core::Result<()> {
276+
self.progress.store(0, Ordering::SeqCst);
276277
let mut tasks: JoinSet<Result<()>> = JoinSet::new();
277278
for _ in 0..self.options.parallel {
278279
let test_instance_clone = Arc::clone(&test_instance);
@@ -283,6 +284,7 @@ impl PerfRunner {
283284
// let context =
284285
// TestContext::new(package_dir, module_name, " test_name_copy.as_str()")?;
285286

287+
tokio::task::yield_now().await;
286288
loop {
287289
test_instance_clone.run(/*&context*/).await?;
288290
progress.fetch_add(1, Ordering::SeqCst);
@@ -295,12 +297,16 @@ impl PerfRunner {
295297
_ = tokio::time::sleep(timeout) => {println!("Timeout reached, stopping test tasks: {:?}", start.elapsed());},
296298
_ = tasks.join_all() => {println!("All test tasks completed: {:?}", start.elapsed());},
297299
_ = async {
300+
let mut last_count = 0;
298301
loop {
299302
tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;
300-
println!("{:<10?} elapsed: {:.5} op/sec, {:4} sec/operation.",
301-
start.elapsed(),
302-
self.progress.load(Ordering::SeqCst) as f64 / start.elapsed().as_secs_f64(),
303-
Duration::seconds_f64( start.elapsed().as_secs_f64() / self.progress.load(Ordering::SeqCst) as f64 ));
303+
let current_total = self.progress.load(Ordering::SeqCst);
304+
// println!("{:<10?} elapsed: {:.5} op/sec, {:4} sec/operation.",
305+
// start.elapsed(),
306+
// self.progress.load(Ordering::SeqCst) as f64 / start.elapsed().as_secs_f64(),
307+
// Duration::seconds_f64( start.elapsed().as_secs_f64() / self.progress.load(Ordering::SeqCst) as f64 ));
308+
println!("Current {:3}, Total {:5} {:4}", current_total - last_count, current_total, Duration::seconds_f64( start.elapsed().as_secs_f64() / self.progress.load(Ordering::SeqCst) as f64 ));
309+
last_count = current_total;
304310
}
305311
}, if !self.options.disable_progress => {},
306312
);
@@ -323,7 +329,7 @@ impl PerfRunner {
323329
// * Sync - run a synchronous version of the test
324330

325331
/// Constructs a `clap::Command` from the provided test metadata.
326-
fn get_command_from_metadata(tests: &[TestMetadata]) -> clap::Command {
332+
fn get_command_from_metadata(tests: &[PerfTestMetadata]) -> clap::Command {
327333
let mut command = clap::Command::new("perf-tests")
328334
.about("Run performance tests for the Azure SDK for Rust")
329335
.arg(

sdk/keyvault/azure_security_keyvault_secrets/perf/get_secret.rs

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,23 @@
11
// Copyright (c) Microsoft Corporation. All rights reserved.
22
// Licensed under the MIT License.
33

4+
//! Keyvault Secrets performance tests.
5+
//!
6+
//! This test measures the performance of getting a secret from Azure Key Vault.
7+
//! It sets up a secret in the Key Vault during the setup phase and then repeatedly retrieves it
8+
//! during the run phase. The test can be configured with the vault URL via command line arguments
9+
//! to target different Key Vault instances.
10+
//!
11+
//! To run the test, use the following command line arguments:
12+
//!
13+
//! cargo test --package azure_security_keyvault_secrets --test performance_tests -- --duration 10 --parallel 20 get_secret -u https://<my_vault>.vault.azure.net/
14+
//!
15+
416
use std::sync::OnceLock;
517

618
use azure_core::Result;
719
use azure_core_test::{
8-
perf::{CreatePerfTestReturn, PerfRunner, PerfTest, TestMetadata, TestOption},
20+
perf::{CreatePerfTestReturn, PerfRunner, PerfTest, PerfTestMetadata, PerfTestOption},
921
TestContext,
1022
};
1123
use azure_security_keyvault_secrets::{models::SetSecretParameters, SecretClient};
@@ -17,11 +29,11 @@ struct GetSecrets {
1729
}
1830

1931
impl GetSecrets {
20-
fn test_metadata() -> TestMetadata {
21-
TestMetadata {
32+
fn test_metadata() -> PerfTestMetadata {
33+
PerfTestMetadata {
2234
name: "get_secret",
2335
description: "Get a secret from Key Vault",
24-
options: vec![TestOption {
36+
options: vec![PerfTestOption {
2537
name: "vault_url",
2638
display_message: "The URL of the Key Vault to use in the test",
2739
mandatory: true,

sdk/storage/azure_storage_blob/Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,8 @@ azure_storage_blob_test.path = "../azure_storage_blob_test"
3737
futures.workspace = true
3838
tokio = { workspace = true, features = ["macros"] }
3939
tracing.workspace = true
40+
41+
[[test]]
42+
name = "performance_tests"
43+
path = "perf/perf_tests.rs"
44+
harness = false
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
use azure_core::{Bytes, Result};
5+
use azure_core_test::{
6+
perf::{CreatePerfTestReturn, PerfRunner, PerfTest, PerfTestMetadata, PerfTestOption},
7+
TestContext,
8+
};
9+
use azure_identity::DeveloperToolsCredential;
10+
use azure_storage_blob::BlobContainerClient;
11+
use futures::TryStreamExt;
12+
13+
pub struct ListBlobTest {
14+
count: u32,
15+
client: BlobContainerClient,
16+
}
17+
18+
impl ListBlobTest {
19+
fn create_list_blob_test(runner: &PerfRunner) -> CreatePerfTestReturn {
20+
async fn create_test(runner: PerfRunner) -> Result<Box<dyn PerfTest>> {
21+
let count: Option<&String> = runner.try_get_test_arg("count")?;
22+
23+
println!("ListBlobTest with count: {:?}", count);
24+
let count = count.expect("count argument is mandatory").parse::<u32>()?;
25+
println!("Parsed count: {}", count);
26+
27+
let endpoint: Option<&String> = runner.try_get_test_arg("endpoint")?;
28+
let endpoint = endpoint.expect("endpoint argument is mandatory").clone();
29+
println!("Using endpoint: {}", endpoint);
30+
31+
let container_name = format!("perf-container-{}", uuid::Uuid::new_v4());
32+
let credential = DeveloperToolsCredential::new(None)?;
33+
let client = BlobContainerClient::new(&endpoint, container_name, credential, None)?;
34+
35+
Ok(Box::new(ListBlobTest { count, client }) as Box<dyn PerfTest>)
36+
}
37+
// Here you would create and return an instance of your performance test.
38+
// For example:
39+
Box::pin(create_test(runner.clone()))
40+
}
41+
42+
pub fn test_metadata() -> PerfTestMetadata {
43+
PerfTestMetadata {
44+
name: "list_blob",
45+
description: "List blobs in a container",
46+
options: vec![
47+
PerfTestOption {
48+
name: "count",
49+
display_message: "The number of blobs to list",
50+
mandatory: true,
51+
short_activator: 'c',
52+
long_activator: "count",
53+
expected_args_len: 1,
54+
..Default::default()
55+
},
56+
PerfTestOption {
57+
name: "endpoint",
58+
display_message: "The endpoint of the blob storage",
59+
mandatory: true,
60+
short_activator: 'e',
61+
long_activator: "endpoint",
62+
expected_args_len: 1,
63+
..Default::default()
64+
},
65+
],
66+
create_test: Self::create_list_blob_test,
67+
}
68+
}
69+
}
70+
71+
#[async_trait::async_trait]
72+
impl PerfTest for ListBlobTest {
73+
async fn setup(&self, _context: &TestContext) -> azure_core::Result<()> {
74+
// Setup code before running the test
75+
76+
let result = self.client.create_container(None).await?;
77+
78+
for i in 0..self.count {
79+
let blob_name = format!("blob-{}", i);
80+
let blob_client = self.client.blob_client(blob_name);
81+
82+
let body = vec![0u8; 1024 * 1024]; // 1 MB blob
83+
let body_bytes = Bytes::from(body);
84+
85+
let result = blob_client.upload(body_bytes.into(), true, 5, None).await?;
86+
}
87+
88+
Ok(())
89+
}
90+
91+
async fn run(&self) -> azure_core::Result<()> {
92+
// The actual performance test code
93+
94+
let mut iterator = self.client.list_blobs(None)?;
95+
while let Some(blob_segment) = iterator.try_next().await? {
96+
let body = blob_segment.into_body()?;
97+
}
98+
99+
Ok(())
100+
}
101+
102+
async fn cleanup(&self, _context: &TestContext) -> azure_core::Result<()> {
103+
// Cleanup code after running the test
104+
Ok(())
105+
}
106+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
/// list_blob performance test.
5+
mod list_blob_test;
6+
7+
use azure_core_test::perf::PerfRunner;
8+
use list_blob_test::ListBlobTest;
9+
10+
#[tokio::main]
11+
async fn main() -> azure_core::Result<()> {
12+
let runner = PerfRunner::new(
13+
env!("CARGO_MANIFEST_DIR"),
14+
"foo",
15+
vec![ListBlobTest::test_metadata()],
16+
)?;
17+
18+
runner.run().await?;
19+
20+
Ok(())
21+
}

0 commit comments

Comments
 (0)