Skip to content

Commit 703474b

Browse files
authored
[ACR] Add Perf tests for Blob upload/download (Azure#35157)
* first steps * Add UploadBlob * Add DownloadBlob * Perf test improvements and client bug fix.
1 parent bf67b90 commit 703474b

File tree

5 files changed

+101
-15
lines changed

5 files changed

+101
-15
lines changed

sdk/containerregistry/Azure.Containers.ContainerRegistry/perf/Azure.Containers.ContainerRegistry.Perf/Infrastructure/ContainerRegistryPerfTest.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44
using System;
55
using System.Collections.Generic;
66
using System.Linq;
7-
using System.Text;
8-
using System.Threading.Tasks;
97
using Azure.Test.Perf;
108
using Microsoft.Azure.Management.ContainerRegistry;
119
using Microsoft.Azure.Management.ContainerRegistry.Models;
@@ -17,6 +15,11 @@ namespace Azure.Containers.ContainerRegistry.Perf
1715
{
1816
public abstract class ContainerRegistryPerfTest : PerfTest<PerfOptions>
1917
{
18+
public const string RepositoryName = $"library/node";
19+
public const string TagName = "test-perf";
20+
21+
public const int BlobSize = 10 * 1024;
22+
2023
public ContainerRegistryPerfTest(PerfOptions options) : base(options)
2124
{
2225
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
using System;
5+
using System.IO;
6+
using System.Threading;
7+
using System.Threading.Tasks;
8+
using Azure.Test.Perf;
9+
10+
namespace Azure.Containers.ContainerRegistry.Perf
11+
{
12+
public sealed class DownloadBlob : ContainerRegistryPerfTest
13+
{
14+
private readonly ContainerRegistryContentClient _client;
15+
16+
private string _digest;
17+
18+
public DownloadBlob(PerfOptions options) : base(options)
19+
{
20+
_client = new ContainerRegistryContentClient(new Uri(PerfTestEnvironment.Instance.Endpoint), ContainerRegistryPerfTest.RepositoryName, PerfTestEnvironment.Instance.Credential);
21+
}
22+
23+
public override async Task SetupAsync()
24+
{
25+
await base.SetupAsync();
26+
27+
using Stream stream = RandomStream.Create(BlobSize);
28+
UploadRegistryBlobResult result = await _client.UploadBlobAsync(stream);
29+
30+
_digest = result.Digest;
31+
}
32+
33+
public override void Run(CancellationToken cancellationToken)
34+
{
35+
_client.DownloadBlobTo(_digest, Stream.Null, cancellationToken);
36+
}
37+
38+
public override async Task RunAsync(CancellationToken cancellationToken)
39+
{
40+
await _client.DownloadBlobToAsync(_digest, Stream.Null, cancellationToken);
41+
}
42+
}
43+
}

sdk/containerregistry/Azure.Containers.ContainerRegistry/perf/Azure.Containers.ContainerRegistry.Perf/Scenarios/ListArtifacts.cs

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,32 +27,29 @@ public override async Task GlobalSetupAsync()
2727
// Global setup code that runs once at the beginning of test execution.
2828
await base.GlobalSetupAsync();
2929

30-
string repository = $"library/node";
31-
string tag = "test-perf";
32-
33-
await ImportImageAsync(PerfTestEnvironment.Instance.Registry, repository, tag);
30+
await ImportImageAsync(PerfTestEnvironment.Instance.Registry, RepositoryName, TagName);
3431
}
3532

3633
public override async Task SetupAsync()
3734
{
3835
await base.SetupAsync();
3936

40-
_repository = _client.GetRepository($"library/node");
37+
_repository = _client.GetRepository(RepositoryName);
4138
}
4239

4340
public override void Run(CancellationToken cancellationToken)
4441
{
4542
foreach (var manifest in _repository.GetAllManifestProperties())
4643
{
47-
_client.GetArtifact($"library/node", manifest.Digest);
44+
_client.GetArtifact(RepositoryName, manifest.Digest);
4845
}
4946
}
5047

5148
public override async Task RunAsync(CancellationToken cancellationToken)
5249
{
5350
await foreach (var manifest in _repository.GetAllManifestPropertiesAsync())
5451
{
55-
_client.GetArtifact($"library/node", manifest.Digest);
52+
_client.GetArtifact(RepositoryName, manifest.Digest);
5653
}
5754
}
5855
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
using System;
5+
using System.IO;
6+
using System.Threading;
7+
using System.Threading.Tasks;
8+
using Azure.Test.Perf;
9+
10+
namespace Azure.Containers.ContainerRegistry.Perf
11+
{
12+
public sealed class UploadBlob : ContainerRegistryPerfTest
13+
{
14+
private readonly ContainerRegistryContentClient _client;
15+
16+
public UploadBlob(PerfOptions options) : base(options)
17+
{
18+
_client = new ContainerRegistryContentClient(new Uri(PerfTestEnvironment.Instance.Endpoint), ContainerRegistryPerfTest.RepositoryName, PerfTestEnvironment.Instance.Credential);
19+
}
20+
21+
public override void Run(CancellationToken cancellationToken)
22+
{
23+
using Stream stream = RandomStream.Create(BlobSize);
24+
_client.UploadBlob(stream, cancellationToken);
25+
}
26+
27+
public override async Task RunAsync(CancellationToken cancellationToken)
28+
{
29+
using Stream stream = RandomStream.Create(BlobSize);
30+
await _client.UploadBlobAsync(stream, cancellationToken);
31+
}
32+
}
33+
}

sdk/containerregistry/Azure.Containers.ContainerRegistry/src/Content/ContainerRegistryContentClient.cs

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33

44
using System;
55
using System.Buffers;
6-
using System.Collections.Generic;
76
using System.Globalization;
87
using System.IO;
98
using System.Security.Cryptography;
@@ -945,7 +944,7 @@ private async Task<Response> DownloadBlobToInternalAsync(string digest, Stream d
945944
int chunkSize = blobSize.HasValue ?
946945
(int)Math.Min(blobSize.Value - bytesDownloaded, options.MaxChunkSize) :
947946
options.MaxChunkSize;
948-
HttpRange range = new HttpRange(bytesDownloaded, chunkSize);
947+
HttpRange range = new(bytesDownloaded, chunkSize);
949948

950949
var chunkResult = async ?
951950
await _blobRestClient.GetChunkAsync(_repositoryName, digest, range.ToString(), cancellationToken).ConfigureAwait(false) :
@@ -954,16 +953,27 @@ await _blobRestClient.GetChunkAsync(_repositoryName, digest, range.ToString(), c
954953
blobSize ??= GetBlobSizeFromContentRange(chunkResult.Headers.ContentRange);
955954
chunkSize = (int)chunkResult.Headers.ContentLength.Value;
956955

956+
int offset = 0;
957+
int length = async ?
958+
await chunkResult.Value.ReadAsync(buffer, offset, chunkSize, cancellationToken).ConfigureAwait(false) :
959+
chunkResult.Value.Read(buffer, offset, chunkSize);
960+
961+
while (offset < chunkSize)
962+
{
963+
offset += length;
964+
length = async ?
965+
await chunkResult.Value.ReadAsync(buffer, offset, chunkSize, cancellationToken).ConfigureAwait(false) :
966+
chunkResult.Value.Read(buffer, offset, chunkSize);
967+
}
968+
969+
sha256.TransformBlock(buffer, 0, chunkSize, buffer, 0);
970+
957971
if (async)
958972
{
959-
await chunkResult.Value.ReadAsync(buffer, 0, chunkSize, cancellationToken).ConfigureAwait(false);
960-
sha256.TransformBlock(buffer, 0, chunkSize, buffer, 0);
961973
await destination.WriteAsync(buffer, 0, chunkSize, cancellationToken).ConfigureAwait(false);
962974
}
963975
else
964976
{
965-
chunkResult.Value.Read(buffer, 0, chunkSize);
966-
sha256.TransformBlock(buffer, 0, chunkSize, buffer, 0);
967977
destination.Write(buffer, 0, chunkSize);
968978
}
969979

0 commit comments

Comments
 (0)