diff --git a/net/Azure.Storage.Blobs.PerfStress/Azure.Storage.Blobs.PerfStress.csproj b/net/Azure.Storage.Blobs.PerfStress/Azure.Storage.Blobs.PerfStress.csproj
index 85dc8744d1c4..caa67e9bf36e 100644
--- a/net/Azure.Storage.Blobs.PerfStress/Azure.Storage.Blobs.PerfStress.csproj
+++ b/net/Azure.Storage.Blobs.PerfStress/Azure.Storage.Blobs.PerfStress.csproj
@@ -6,6 +6,12 @@
true
+
+
+
+
+
+
diff --git a/net/Azure.Storage.Blobs.PerfStress/Core/CircularStream.cs b/net/Azure.Storage.Blobs.PerfStress/Core/CircularStream.cs
index 22eadca39abe..0ecb6509a4af 100644
--- a/net/Azure.Storage.Blobs.PerfStress/Core/CircularStream.cs
+++ b/net/Azure.Storage.Blobs.PerfStress/Core/CircularStream.cs
@@ -86,5 +86,11 @@ public override void Write(byte[] buffer, int offset, int count)
{
throw new NotImplementedException();
}
+
+ protected override void Dispose(bool disposing)
+ {
+ _innerStream.Dispose();
+ base.Dispose(disposing);
+ }
}
}
diff --git a/net/Azure.Storage.Blobs.PerfStress/Core/ContainerTest.cs b/net/Azure.Storage.Blobs.PerfStress/Core/ContainerTest.cs
new file mode 100644
index 000000000000..75a101eb31a5
--- /dev/null
+++ b/net/Azure.Storage.Blobs.PerfStress/Core/ContainerTest.cs
@@ -0,0 +1,36 @@
+using Azure.Test.PerfStress;
+using System;
+using System.Threading.Tasks;
+
+namespace Azure.Storage.Blobs.PerfStress.Core
+{
+ public abstract class ContainerTest : ServiceTest where TOptions : PerfStressOptions
+ {
+ private const string _containerPrefix = "perfstress";
+ protected static string ContainerName { get; private set; }
+
+ static ContainerTest()
+ {
+ ContainerName = _containerPrefix + "-" + Guid.NewGuid().ToString();
+ }
+
+ protected BlobContainerClient BlobContainerClient { get; private set; }
+
+ public ContainerTest(TOptions options) : base(options)
+ {
+ BlobContainerClient = BlobServiceClient.GetBlobContainerClient(ContainerName);
+ }
+
+ public override async Task GlobalSetup()
+ {
+ await base.GlobalSetup();
+ await BlobContainerClient.CreateAsync();
+ }
+
+ public override async Task GlobalCleanup()
+ {
+ await BlobContainerClient.DeleteAsync();
+ await base.GlobalCleanup();
+ }
+ }
+}
diff --git a/net/Azure.Storage.Blobs.PerfStress/Core/ContainerV11Test.cs b/net/Azure.Storage.Blobs.PerfStress/Core/ContainerV11Test.cs
new file mode 100644
index 000000000000..322dbd42c38e
--- /dev/null
+++ b/net/Azure.Storage.Blobs.PerfStress/Core/ContainerV11Test.cs
@@ -0,0 +1,37 @@
+using Azure.Test.PerfStress;
+using Microsoft.Azure.Storage.Blob;
+using System;
+using System.Threading.Tasks;
+
+namespace Azure.Storage.Blobs.PerfStress.Core
+{
+ public abstract class ContainerV11Test : ServiceV11Test where TOptions: PerfStressOptions
+ {
+ private const string _containerPrefix = "perfstress";
+ protected static string ContainerName { get; private set; }
+
+ static ContainerV11Test()
+ {
+ ContainerName = _containerPrefix + "-" + Guid.NewGuid().ToString();
+ }
+
+ protected CloudBlobContainer CloudBlobContainer { get; private set; }
+
+ public ContainerV11Test(TOptions options) : base(options)
+ {
+ CloudBlobContainer = CloudBlobClient.GetContainerReference(ContainerName);
+ }
+
+ public override async Task GlobalSetup()
+ {
+ await base.GlobalSetup();
+ await CloudBlobContainer.CreateAsync();
+ }
+
+ public override async Task GlobalCleanup()
+ {
+ await CloudBlobContainer.DeleteAsync();
+ await base.GlobalCleanup();
+ }
+ }
+}
diff --git a/net/Azure.Storage.Blobs.PerfStress/Core/CountOptions.cs b/net/Azure.Storage.Blobs.PerfStress/Core/CountOptions.cs
new file mode 100644
index 000000000000..80e956633b69
--- /dev/null
+++ b/net/Azure.Storage.Blobs.PerfStress/Core/CountOptions.cs
@@ -0,0 +1,11 @@
+using Azure.Test.PerfStress;
+using CommandLine;
+
+namespace Azure.Storage.Blobs.PerfStress.Core
+{
+ public class CountOptions : PerfStressOptions
+ {
+ [Option('c', "count", Default = 100, HelpText = "Number of blobs")]
+ public int Count { get; set; }
+ }
+}
diff --git a/net/Azure.Storage.Blobs.PerfStress/Core/ParallelTransferOptionsOptions.cs b/net/Azure.Storage.Blobs.PerfStress/Core/ParallelTransferOptionsOptions.cs
index 16bcd17b6576..401cb9f5b701 100644
--- a/net/Azure.Storage.Blobs.PerfStress/Core/ParallelTransferOptionsOptions.cs
+++ b/net/Azure.Storage.Blobs.PerfStress/Core/ParallelTransferOptionsOptions.cs
@@ -1,13 +1,44 @@
-using CommandLine;
+using Azure.Storage.Common;
+using CommandLine;
namespace Azure.Storage.Blobs.PerfStress.Core
{
public class ParallelTransferOptionsOptions : SizeOptions
{
+ private int? _maximumTransferLength;
+ private int? _maximumThreadCount;
+
[Option('l', "maximumTransferLength")]
- public int? MaximumTransferLength { get; set; }
+ public int? MaximumTransferLength
+ {
+ get => _maximumTransferLength;
+ set
+ {
+ _maximumTransferLength = value;
+ UpdateParallelTransferOptions();
+ }
+ }
[Option('t', "maximumThreadCount")]
- public int? MaximumThreadCount { get; set; }
+ public int? MaximumThreadCount
+ {
+ get => _maximumThreadCount;
+ set
+ {
+ _maximumThreadCount = value;
+ UpdateParallelTransferOptions();
+ }
+ }
+
+ public ParallelTransferOptions ParallelTransferOptions { get; private set; } = new ParallelTransferOptions();
+
+ private void UpdateParallelTransferOptions()
+ {
+ ParallelTransferOptions = new ParallelTransferOptions()
+ {
+ MaximumThreadCount = MaximumThreadCount,
+ MaximumTransferLength = MaximumTransferLength
+ };
+ }
}
}
diff --git a/net/Azure.Storage.Blobs.PerfStress/Core/ParallelTransferTest.cs b/net/Azure.Storage.Blobs.PerfStress/Core/ParallelTransferTest.cs
deleted file mode 100644
index 89fef548ce8e..000000000000
--- a/net/Azure.Storage.Blobs.PerfStress/Core/ParallelTransferTest.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-using Azure.Storage.Common;
-
-namespace Azure.Storage.Blobs.PerfStress.Core
-{
- public abstract class ParallelTransferTest : RandomDataTest where TOptions : ParallelTransferOptionsOptions
- {
- public ParallelTransferTest(string id, TOptions options) : base(id, options)
- {
- ParallelTransferOptions = new ParallelTransferOptions()
- {
- MaximumThreadCount = options.MaximumThreadCount,
- MaximumTransferLength = options.MaximumTransferLength
- };
- }
-
- protected ParallelTransferOptions ParallelTransferOptions { get; private set; }
- }
-}
diff --git a/net/Azure.Storage.Blobs.PerfStress/Core/RandomDataTest.cs b/net/Azure.Storage.Blobs.PerfStress/Core/RandomDataTest.cs
deleted file mode 100644
index 7dc90d958be2..000000000000
--- a/net/Azure.Storage.Blobs.PerfStress/Core/RandomDataTest.cs
+++ /dev/null
@@ -1,24 +0,0 @@
-using System;
-using System.IO;
-
-namespace Azure.Storage.Blobs.PerfStress.Core
-{
- public abstract class RandomDataTest : StorageTest where TOptions : SizeOptions
- {
- private readonly byte[] _randomData;
-
- public RandomDataTest(string id, TOptions options) : base(id, options)
- {
- _randomData = new byte[1024 * 1024];
- (new Random(0)).NextBytes(_randomData);
- }
-
- protected Stream RandomStream => new CircularStream(new MemoryStream(_randomData, writable: false), Options.Size);
-
- public override void Dispose()
- {
- RandomStream.Dispose();
- base.Dispose();
- }
- }
-}
diff --git a/net/Azure.Storage.Blobs.PerfStress/Core/RandomDataV11Test.cs b/net/Azure.Storage.Blobs.PerfStress/Core/RandomDataV11Test.cs
deleted file mode 100644
index b0cf3152125a..000000000000
--- a/net/Azure.Storage.Blobs.PerfStress/Core/RandomDataV11Test.cs
+++ /dev/null
@@ -1,24 +0,0 @@
-using System;
-using System.IO;
-
-namespace Azure.Storage.Blobs.PerfStress.Core
-{
- public abstract class RandomDataV11Test : StorageV11Test where TOptions : SizeOptions
- {
- private readonly byte[] _randomData;
-
- public RandomDataV11Test(string id, TOptions options) : base(id, options)
- {
- _randomData = new byte[1024 * 1024];
- (new Random(0)).NextBytes(_randomData);
- }
-
- protected Stream RandomStream => new CircularStream(new MemoryStream(_randomData, writable: false), Options.Size);
-
- public override void Dispose()
- {
- RandomStream.Dispose();
- base.Dispose();
- }
- }
-}
diff --git a/net/Azure.Storage.Blobs.PerfStress/Core/RandomStream.cs b/net/Azure.Storage.Blobs.PerfStress/Core/RandomStream.cs
new file mode 100644
index 000000000000..af1835b3e723
--- /dev/null
+++ b/net/Azure.Storage.Blobs.PerfStress/Core/RandomStream.cs
@@ -0,0 +1,17 @@
+using System;
+using System.IO;
+
+namespace Azure.Storage.Blobs.PerfStress.Core
+{
+ public static class RandomStream
+ {
+ private static readonly Lazy _randomBytes = new Lazy(() =>
+ {
+ var randomData = new byte[1024 * 1024];
+ (new Random(0)).NextBytes(randomData);
+ return randomData;
+ });
+
+ public static Stream Create(long size) => new CircularStream(new MemoryStream(_randomBytes.Value, writable: false), size);
+ }
+}
diff --git a/net/Azure.Storage.Blobs.PerfStress/Core/StorageTest.cs b/net/Azure.Storage.Blobs.PerfStress/Core/ServiceTest.cs
similarity index 57%
rename from net/Azure.Storage.Blobs.PerfStress/Core/StorageTest.cs
rename to net/Azure.Storage.Blobs.PerfStress/Core/ServiceTest.cs
index 21823e487c46..1b4dfba51a97 100644
--- a/net/Azure.Storage.Blobs.PerfStress/Core/StorageTest.cs
+++ b/net/Azure.Storage.Blobs.PerfStress/Core/ServiceTest.cs
@@ -5,19 +5,12 @@
namespace Azure.Storage.Blobs.PerfStress
{
- public abstract class StorageTest : PerfStressTest where TOptions: PerfStressOptions
+ public abstract class ServiceTest : PerfStressTest where TOptions: PerfStressOptions
{
- private const string _containerName = "perfstress";
-
protected BlobServiceClient BlobServiceClient { get; private set; }
- protected BlobContainerClient BlobContainerClient { get; private set; }
-
- protected BlobClient BlobClient { get; private set; }
-
- public StorageTest(string id, TOptions options) : base(id, options)
+ public ServiceTest(TOptions options) : base(options)
{
- var blobName = this.GetType().Name.ToLowerInvariant() + id;
var connectionString = Environment.GetEnvironmentVariable("STORAGE_CONNECTION_STRING");
if (string.IsNullOrEmpty(connectionString))
@@ -33,17 +26,6 @@ public StorageTest(string id, TOptions options) : base(id, options)
blobClientOptions.Transport = new HttpClientTransport(httpClient);
BlobServiceClient = new BlobServiceClient(connectionString, blobClientOptions);
- try
- {
- BlobServiceClient.CreateBlobContainer(_containerName);
- }
- catch (StorageRequestFailedException)
- {
- }
-
- BlobContainerClient = BlobServiceClient.GetBlobContainerClient(_containerName);
-
- BlobClient = BlobContainerClient.GetBlobClient(blobName);
}
}
}
diff --git a/net/Azure.Storage.Blobs.PerfStress/Core/ServiceV11Test.cs b/net/Azure.Storage.Blobs.PerfStress/Core/ServiceV11Test.cs
new file mode 100644
index 000000000000..a4414abbddea
--- /dev/null
+++ b/net/Azure.Storage.Blobs.PerfStress/Core/ServiceV11Test.cs
@@ -0,0 +1,27 @@
+using Azure.Test.PerfStress;
+using Microsoft.Azure.Storage;
+using Microsoft.Azure.Storage.Blob;
+using System;
+
+namespace Azure.Storage.Blobs.PerfStress.Core
+{
+ public abstract class ServiceV11Test : PerfStressTest where TOptions : PerfStressOptions
+ {
+ protected CloudBlobClient CloudBlobClient { get; private set; }
+
+ public ServiceV11Test(TOptions options) : base(options)
+ {
+ var connectionString = Environment.GetEnvironmentVariable("STORAGE_CONNECTION_STRING");
+
+ if (string.IsNullOrEmpty(connectionString))
+ {
+ throw new InvalidOperationException("Undefined environment variable STORAGE_CONNECTION_STRING");
+ }
+
+ CloudStorageAccount.TryParse(connectionString, out var storageAccount);
+
+
+ CloudBlobClient = storageAccount.CreateCloudBlobClient();
+ }
+ }
+}
diff --git a/net/Azure.Storage.Blobs.PerfStress/Core/StorageV11Test.cs b/net/Azure.Storage.Blobs.PerfStress/Core/StorageV11Test.cs
deleted file mode 100644
index 74ea4eeb36a3..000000000000
--- a/net/Azure.Storage.Blobs.PerfStress/Core/StorageV11Test.cs
+++ /dev/null
@@ -1,43 +0,0 @@
-using Azure.Test.PerfStress;
-using Microsoft.Azure.Storage;
-using Microsoft.Azure.Storage.Blob;
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace Azure.Storage.Blobs.PerfStress.Core
-{
- public abstract class StorageV11Test : PerfStressTest where TOptions : PerfStressOptions
- {
- private const string _containerName = "perfstress";
-
- protected CloudBlockBlob CloudBlockBlob { get; private set; }
-
- public StorageV11Test(string id, TOptions options) : base(id, options)
- {
- var blobName = this.GetType().Name.ToLowerInvariant() + id;
- var connectionString = Environment.GetEnvironmentVariable("STORAGE_CONNECTION_STRING");
-
- if (string.IsNullOrEmpty(connectionString))
- {
- throw new InvalidOperationException("Undefined environment variable STORAGE_CONNECTION_STRING");
- }
-
- CloudStorageAccount.TryParse(connectionString, out var storageAccount);
- var cloudBlobClient = storageAccount.CreateCloudBlobClient();
-
- var cloudBlobContainer = cloudBlobClient.GetContainerReference(_containerName);
-
- try
- {
- cloudBlobContainer.Create();
- }
- catch (StorageException)
- {
- }
-
-
- CloudBlockBlob = cloudBlobContainer.GetBlockBlobReference(blobName);
- }
- }
-}
diff --git a/net/Azure.Storage.Blobs.PerfStress/DownloadTest.cs b/net/Azure.Storage.Blobs.PerfStress/DownloadTest.cs
index 2db0b041011f..21ad71081213 100644
--- a/net/Azure.Storage.Blobs.PerfStress/DownloadTest.cs
+++ b/net/Azure.Storage.Blobs.PerfStress/DownloadTest.cs
@@ -5,42 +5,33 @@
namespace Azure.Storage.Blobs.PerfStress
{
- public class DownloadTest : ParallelTransferTest
+ public class DownloadTest : ContainerTest
{
- public DownloadTest(string id, ParallelTransferOptionsOptions options) : base(id, options)
- {
- try
- {
- BlobClient.Delete();
- }
- catch (StorageRequestFailedException)
- {
- }
+ private readonly BlobClient _blobClient;
- BlobClient.Upload(RandomStream);
+ public DownloadTest(ParallelTransferOptionsOptions options) : base(options)
+ {
+ _blobClient = BlobContainerClient.GetBlobClient("downloadtest");
}
- public override void Run(CancellationToken cancellationToken)
+ public override async Task GlobalSetup()
{
- BlobClient.Download(Stream.Null, parallelTransferOptions: ParallelTransferOptions, cancellationToken: cancellationToken);
+ await base.GlobalSetup();
+
+ using var stream = RandomStream.Create(Options.Size);
+
+ // No need to delete file in GlobalCleanup(), since ContainerTest.GlobalCleanup() deletes the whole container
+ await _blobClient.UploadAsync(stream);
}
- public override async Task RunAsync(CancellationToken cancellationToken)
+ public override void Run(CancellationToken cancellationToken)
{
- await BlobClient.DownloadAsync(Stream.Null, parallelTransferOptions: ParallelTransferOptions, cancellationToken: cancellationToken);
+ _blobClient.Download(Stream.Null, parallelTransferOptions: Options.ParallelTransferOptions, cancellationToken: cancellationToken);
}
- public override void Dispose()
+ public override async Task RunAsync(CancellationToken cancellationToken)
{
- try
- {
- BlobClient.Delete();
- }
- catch (StorageRequestFailedException)
- {
- }
-
- base.Dispose();
+ await _blobClient.DownloadAsync(Stream.Null, parallelTransferOptions: Options.ParallelTransferOptions, cancellationToken: cancellationToken);
}
}
}
diff --git a/net/Azure.Storage.Blobs.PerfStress/DownloadV11Test.cs b/net/Azure.Storage.Blobs.PerfStress/DownloadV11Test.cs
index c5d0fe3c936c..d464e0d36fa7 100644
--- a/net/Azure.Storage.Blobs.PerfStress/DownloadV11Test.cs
+++ b/net/Azure.Storage.Blobs.PerfStress/DownloadV11Test.cs
@@ -1,47 +1,38 @@
using Azure.Storage.Blobs.PerfStress.Core;
-using Microsoft.Azure.Storage;
+using Microsoft.Azure.Storage.Blob;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
namespace Azure.Storage.Blobs.PerfStress
{
- public class DownloadV11Test : RandomDataV11Test
+ public class DownloadV11Test : ContainerV11Test
{
- public DownloadV11Test(string id, SizeOptions options) : base(id, options)
- {
- try
- {
- CloudBlockBlob.Delete();
- }
- catch (StorageException)
- {
- }
+ private readonly CloudBlockBlob _cloudBlockBlob;
- CloudBlockBlob.UploadFromStream(RandomStream);
- }
-
- public override void Run(CancellationToken cancellationToken)
+ public DownloadV11Test(SizeOptions options) : base(options)
{
- CloudBlockBlob.DownloadToStream(Stream.Null);
+ _cloudBlockBlob = CloudBlobContainer.GetBlockBlobReference("downloadv11test");
}
- public override async Task RunAsync(CancellationToken cancellationToken)
+ public override async Task GlobalSetup()
{
- await CloudBlockBlob.DownloadToStreamAsync(Stream.Null, cancellationToken);
+ await base.GlobalSetup();
+
+ using var stream = RandomStream.Create(Options.Size);
+
+ // No need to delete file in GlobalCleanup(), since ContainerV11Test.GlobalCleanup() deletes the whole container
+ await _cloudBlockBlob.UploadFromStreamAsync(stream);
}
- public override void Dispose()
+ public override void Run(CancellationToken cancellationToken)
{
- try
- {
- CloudBlockBlob.Delete();
- }
- catch (StorageException)
- {
- }
+ _cloudBlockBlob.DownloadToStream(Stream.Null);
+ }
- base.Dispose();
+ public override async Task RunAsync(CancellationToken cancellationToken)
+ {
+ await _cloudBlockBlob.DownloadToStreamAsync(Stream.Null, cancellationToken);
}
}
}
diff --git a/net/Azure.Storage.Blobs.PerfStress/GetBlobsTest.cs b/net/Azure.Storage.Blobs.PerfStress/GetBlobsTest.cs
new file mode 100644
index 000000000000..4a6636e10d99
--- /dev/null
+++ b/net/Azure.Storage.Blobs.PerfStress/GetBlobsTest.cs
@@ -0,0 +1,40 @@
+using Azure.Storage.Blobs.PerfStress.Core;
+using System;
+using System.IO;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Azure.Storage.Blobs.PerfStress
+{
+ public class GetBlobsTest : ContainerTest
+ {
+ public GetBlobsTest(CountOptions options) : base(options)
+ {
+ }
+
+ public override async Task GlobalSetup()
+ {
+ await base.GlobalSetup();
+
+ var uploadTasks = new Task[Options.Count];
+ for (var i = 0; i < uploadTasks.Length; i++)
+ {
+ var blobName = "getblobstest-" + Guid.NewGuid().ToString();
+ uploadTasks[i] = BlobContainerClient.UploadBlobAsync(blobName, Stream.Null);
+ }
+ await Task.WhenAll(uploadTasks);
+ }
+
+ public override void Run(CancellationToken cancellationToken)
+ {
+ // Enumerate collection to ensure all BlobItems are downloaded
+ foreach (var _ in BlobContainerClient.GetBlobs(cancellationToken: cancellationToken));
+ }
+
+ public override async Task RunAsync(CancellationToken cancellationToken)
+ {
+ // Enumerate collection to ensure all BlobItems are downloaded
+ await foreach (var _ in BlobContainerClient.GetBlobsAsync(cancellationToken: cancellationToken)) { }
+ }
+ }
+}
diff --git a/net/Azure.Storage.Blobs.PerfStress/GetBlobsV11Test.cs b/net/Azure.Storage.Blobs.PerfStress/GetBlobsV11Test.cs
new file mode 100644
index 000000000000..5ef85351fc01
--- /dev/null
+++ b/net/Azure.Storage.Blobs.PerfStress/GetBlobsV11Test.cs
@@ -0,0 +1,48 @@
+using Azure.Storage.Blobs.PerfStress.Core;
+using Microsoft.Azure.Storage.Blob;
+using System;
+using System.IO;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Azure.Storage.Blobs.PerfStress
+{
+ public class GetBlobsV11Test : ContainerV11Test
+ {
+ public GetBlobsV11Test(CountOptions options) : base(options) { }
+
+ public override async Task GlobalSetup()
+ {
+ await base.GlobalSetup();
+
+ var uploadTasks = new Task[Options.Count];
+ for (var i = 0; i < uploadTasks.Length; i++)
+ {
+ var blobName = "getblobstest-" + Guid.NewGuid().ToString();
+ uploadTasks[i] = CloudBlobContainer.GetBlockBlobReference(blobName).UploadFromStreamAsync(Stream.Null);
+ }
+ await Task.WhenAll(uploadTasks);
+ }
+
+ public override void Run(CancellationToken cancellationToken)
+ {
+ // Enumerate collection to ensure all IListBlobItems are downloaded
+ foreach (var _ in CloudBlobContainer.ListBlobs()) { }
+ }
+
+ public override async Task RunAsync(CancellationToken cancellationToken)
+ {
+ BlobContinuationToken continuationToken = null;
+ do
+ {
+ var result = await CloudBlobContainer.ListBlobsSegmentedAsync(continuationToken, cancellationToken);
+ continuationToken = result.ContinuationToken;
+
+ // Enumerate collection to ensure all IListBlobItems are downloaded
+ foreach (var _ in result.Results) { }
+ }
+ while (continuationToken != null);
+ }
+
+ }
+}
diff --git a/net/Azure.Storage.Blobs.PerfStress/UploadTest.cs b/net/Azure.Storage.Blobs.PerfStress/UploadTest.cs
index a87c0193925d..8afa748a8c6a 100644
--- a/net/Azure.Storage.Blobs.PerfStress/UploadTest.cs
+++ b/net/Azure.Storage.Blobs.PerfStress/UploadTest.cs
@@ -1,42 +1,34 @@
using Azure.Storage.Blobs.PerfStress.Core;
+using System;
using System.Threading;
using System.Threading.Tasks;
namespace Azure.Storage.Blobs.PerfStress
{
- public class UploadTest : ParallelTransferTest
+ public class UploadTest : ContainerTest
{
- public UploadTest(string id, ParallelTransferOptionsOptions options) : base(id, options)
+ private readonly BlobClient _blobClient;
+
+ public UploadTest(ParallelTransferOptionsOptions options) : base(options)
{
- try
- {
- BlobClient.Delete();
- }
- catch (StorageRequestFailedException)
- {
- }
+ var blobName = "uploadtest-" + Guid.NewGuid().ToString();
+ _blobClient = BlobContainerClient.GetBlobClient(blobName);
}
public override void Run(CancellationToken cancellationToken)
{
- BlobClient.Upload(RandomStream, parallelTransferOptions: ParallelTransferOptions, cancellationToken: cancellationToken);
+ using var stream = RandomStream.Create(Options.Size);
+
+ // No need to delete file in Cleanup(), since ContainerTest.GlobalCleanup() deletes the whole container
+ _blobClient.Upload(stream, parallelTransferOptions: Options.ParallelTransferOptions, cancellationToken: cancellationToken);
}
public override async Task RunAsync(CancellationToken cancellationToken)
{
- await BlobClient.UploadAsync(RandomStream, parallelTransferOptions: ParallelTransferOptions, cancellationToken: cancellationToken);
- }
+ using var stream = RandomStream.Create(Options.Size);
- public override void Dispose()
- {
- try
- {
- BlobClient.Delete();
- }
- catch (StorageRequestFailedException)
- {
- }
- base.Dispose();
+ // No need to delete file in Cleanup(), since ContainerTest.GlobalCleanup() deletes the whole container
+ await _blobClient.UploadAsync(stream, parallelTransferOptions: Options.ParallelTransferOptions, cancellationToken: cancellationToken);
}
}
}
diff --git a/net/Azure.Storage.Blobs.PerfStress/UploadV11Test.cs b/net/Azure.Storage.Blobs.PerfStress/UploadV11Test.cs
index 0bec6c26668b..d520812745e5 100644
--- a/net/Azure.Storage.Blobs.PerfStress/UploadV11Test.cs
+++ b/net/Azure.Storage.Blobs.PerfStress/UploadV11Test.cs
@@ -1,45 +1,35 @@
using Azure.Storage.Blobs.PerfStress.Core;
-using Microsoft.Azure.Storage;
-using System.IO;
+using Microsoft.Azure.Storage.Blob;
+using System;
using System.Threading;
using System.Threading.Tasks;
namespace Azure.Storage.Blobs.PerfStress
{
- public class UploadV11Test : RandomDataV11Test
+ public class UploadV11Test : ContainerV11Test
{
- public UploadV11Test(string id, SizeOptions options) : base(id, options)
+ private readonly CloudBlockBlob _cloudBlockBlob;
+
+ public UploadV11Test(SizeOptions options) : base(options)
{
- try
- {
- CloudBlockBlob.Delete();
- }
- catch (StorageException)
- {
- }
+ var blobName = "uploadv11test-" + Guid.NewGuid().ToString();
+ _cloudBlockBlob = CloudBlobContainer.GetBlockBlobReference(blobName);
}
public override void Run(CancellationToken cancellationToken)
{
- CloudBlockBlob.UploadFromStream(RandomStream);
- }
+ using var stream = RandomStream.Create(Options.Size);
- public override async Task RunAsync(CancellationToken cancellationToken)
- {
- await CloudBlockBlob.UploadFromStreamAsync(RandomStream, cancellationToken);
+ // No need to delete file in Cleanup(), since ContainerTest.GlobalCleanup() deletes the whole container
+ _cloudBlockBlob.UploadFromStream(stream);
}
- public override void Dispose()
+ public override async Task RunAsync(CancellationToken cancellationToken)
{
- try
- {
- CloudBlockBlob.Delete();
- }
- catch (StorageException)
- {
- }
+ using var stream = RandomStream.Create(Options.Size);
- base.Dispose();
+ // No need to delete file in Cleanup(), since ContainerTest.GlobalCleanup() deletes the whole container
+ await _cloudBlockBlob.UploadFromStreamAsync(stream, cancellationToken);
}
}
}
diff --git a/net/Azure.Test.PerfStress/IPerfStressTest.cs b/net/Azure.Test.PerfStress/IPerfStressTest.cs
index 886a925fb9f1..85293f469dd4 100644
--- a/net/Azure.Test.PerfStress/IPerfStressTest.cs
+++ b/net/Azure.Test.PerfStress/IPerfStressTest.cs
@@ -1,12 +1,15 @@
-using System;
-using System.Threading;
+using System.Threading;
using System.Threading.Tasks;
namespace Azure.Test.PerfStress
{
- internal interface IPerfStressTest : IDisposable
+ internal interface IPerfStressTest
{
+ Task GlobalSetup();
+ Task Setup();
void Run(CancellationToken cancellationToken);
Task RunAsync(CancellationToken cancellationToken);
+ Task Cleanup();
+ Task GlobalCleanup();
}
}
diff --git a/net/Azure.Test.PerfStress/PerfStressOptions.cs b/net/Azure.Test.PerfStress/PerfStressOptions.cs
index 48c36e45852d..3596d2179444 100644
--- a/net/Azure.Test.PerfStress/PerfStressOptions.cs
+++ b/net/Azure.Test.PerfStress/PerfStressOptions.cs
@@ -4,13 +4,16 @@ namespace Azure.Test.PerfStress
{
public class PerfStressOptions
{
- [Option("sync")]
- public bool Sync { get; set; }
-
[Option('d', "duration", Default = 10, HelpText = "Duration of test in seconds")]
public int Duration { get; set; }
+ [Option("no-cleanup", HelpText = "Disables test cleanup")]
+ public bool NoCleanup { get; set; }
+
[Option('p', "parallel", Default = 1, HelpText = "Number of operations to execute in parallel")]
public int Parallel { get; set; }
+
+ [Option("sync", HelpText = "Runs sync version of test")]
+ public bool Sync { get; set; }
}
}
diff --git a/net/Azure.Test.PerfStress/PerfStressProgram.cs b/net/Azure.Test.PerfStress/PerfStressProgram.cs
index 67a187a557e7..2aac437041ac 100644
--- a/net/Azure.Test.PerfStress/PerfStressProgram.cs
+++ b/net/Azure.Test.PerfStress/PerfStressProgram.cs
@@ -52,45 +52,73 @@ private static async Task Run(Type testType, PerfStressOptions options)
var duration = TimeSpan.FromSeconds(options.Duration);
- var tests = CreateTests(testType, options);
+ var tests = new IPerfStressTest[options.Parallel];
+ for (var i = 0; i < options.Parallel; i++)
+ {
+ tests[i] = (IPerfStressTest)Activator.CreateInstance(testType, options);
+ }
try
{
- using var cts = new CancellationTokenSource(duration);
- var cancellationToken = cts.Token;
+ await tests[0].GlobalSetup();
- _ = PrintStatusAsync(cancellationToken);
-
- if (options.Sync)
+ try
{
- var threads = new Thread[options.Parallel];
-
+ var setupTasks = new Task[options.Parallel];
for (var i = 0; i < options.Parallel; i++)
{
- var j = i;
- threads[i] = new Thread(() => RunLoop(tests[j], cancellationToken));
- threads[i].Start();
+ setupTasks[i] = tests[i].Setup();
}
- for (var i = 0; i < options.Parallel; i++)
+ await Task.WhenAll(setupTasks);
+
+ using var cts = new CancellationTokenSource(duration);
+ var cancellationToken = cts.Token;
+
+ _ = PrintStatusAsync(cancellationToken);
+
+ if (options.Sync)
+ {
+ var threads = new Thread[options.Parallel];
+
+ for (var i = 0; i < options.Parallel; i++)
+ {
+ var j = i;
+ threads[i] = new Thread(() => RunLoop(tests[j], cancellationToken));
+ threads[i].Start();
+ }
+ for (var i = 0; i < options.Parallel; i++)
+ {
+ threads[i].Join();
+ }
+ }
+ else
{
- threads[i].Join();
+ var tasks = new Task[options.Parallel];
+ for (var i = 0; i < options.Parallel; i++)
+ {
+ tasks[i] = RunLoopAsync(tests[i], cancellationToken);
+ }
+ await Task.WhenAll(tasks);
}
}
- else
+ finally
{
- var tasks = new Task[options.Parallel];
- for (var i = 0; i < options.Parallel; i++)
+ if (!options.NoCleanup)
{
- tasks[i] = RunLoopAsync(tests[i], cancellationToken);
+ var cleanupTasks = new Task[options.Parallel];
+ for (var i = 0; i < options.Parallel; i++)
+ {
+ cleanupTasks[i] = tests[i].Cleanup();
+ }
+ await Task.WhenAll(cleanupTasks);
}
- await Task.WhenAll(tasks);
}
}
finally
{
- for (var i = 0; i < options.Parallel; i++)
+ if (!options.NoCleanup)
{
- tests[i]?.Dispose();
+ await tests[0].GlobalCleanup();
}
}
@@ -104,28 +132,6 @@ private static async Task Run(Type testType, PerfStressOptions options)
Console.WriteLine();
}
- private static IPerfStressTest[] CreateTests(Type testType, PerfStressOptions options)
- {
- var tests = new IPerfStressTest[options.Parallel];
- var threads = new Thread[options.Parallel];
-
- for (var i=0; i < options.Parallel; i++)
- {
- var j = i;
- threads[i] = new Thread(() =>
- {
- tests[j] = (IPerfStressTest)Activator.CreateInstance(testType, j.ToString(), options);
- });
- threads[i].Start();
- }
- for (var i = 0; i < options.Parallel; i++)
- {
- threads[i].Join();
- }
-
- return tests;
- }
-
private static void RunLoop(IPerfStressTest test, CancellationToken cancellationToken)
{
var sw = Stopwatch.StartNew();
@@ -210,7 +216,7 @@ private static Type[] GetOptionTypes(IEnumerable testTypes)
foreach (var t in testTypes)
{
- var baseOptionsType = t.GetConstructors().First().GetParameters()[1].ParameterType;
+ var baseOptionsType = t.GetConstructors().First().GetParameters()[0].ParameterType;
var tb = mb.DefineType(t.Name + "Options", TypeAttributes.Public, baseOptionsType);
var attrCtor = typeof(VerbAttribute).GetConstructor(new Type[] { typeof(string) });
diff --git a/net/Azure.Test.PerfStress/PerfStressTest.cs b/net/Azure.Test.PerfStress/PerfStressTest.cs
index dafc3caaf50b..45ab2392d5f1 100644
--- a/net/Azure.Test.PerfStress/PerfStressTest.cs
+++ b/net/Azure.Test.PerfStress/PerfStressTest.cs
@@ -5,22 +5,35 @@ namespace Azure.Test.PerfStress
{
public abstract class PerfStressTest : IPerfStressTest where TOptions : PerfStressOptions
{
- protected string Id { get; private set; }
-
protected TOptions Options { get; private set; }
- public PerfStressTest(string id, TOptions options)
+ public PerfStressTest(TOptions options)
{
- Id = id;
Options = options;
}
+ public virtual Task GlobalSetup()
+ {
+ return Task.CompletedTask;
+ }
+
+ public virtual Task Setup()
+ {
+ return Task.CompletedTask;
+ }
+
public abstract void Run(CancellationToken cancellationToken);
public abstract Task RunAsync(CancellationToken cancellationToken);
- public virtual void Dispose()
+ public virtual Task Cleanup()
+ {
+ return Task.CompletedTask;
+ }
+
+ public virtual Task GlobalCleanup()
{
+ return Task.CompletedTask;
}
}
}