Skip to content

Commit

Permalink
[Perf Tests] Storage blob perf tests - track 1 and track 2 (#12737)
Browse files Browse the repository at this point in the history
### Depends on #12662

### Changes in the PR
- Track 2 tests are part of the test folder, which would be compiled along with the regular tests and would require changes if the API is updated
- Track 1 tests - a separate npm project, takes dependence on the perf package, doesn't get compiled along with the regular tests

### To run track 2 perf tests
1. Build the storage-blob package `rush build -t storage-blob`.
2. Navigate to `storage-blob` folder `cd sdk\storage\storage-blob\`.
3. Create a storage account and populate the .env file at `storage\storage-blob` folder with `ACCOUNT_NAME` and `ACCOUNT_KEY` variables.
4. Run the tests as follows
   - download
     - `npm run perfstress-test:node -- StorageBlobDownloadTest --warmup 2 --duration 7 --iterations 2 --parallel 2`
   - upload
     - `npm run perfstress-test:node -- StorageBlobUploadTest --warmup 2 --duration 7 --iterations 2 --parallel 2`
   - upload file
     - `npm run perfstress-test:node -- StorageBlobUploadFileTest --warmup 2 --duration 7 --iterations 2 --parallel 2`
   - list blobs
     - `npm run perfstress-test:node -- StorageBlobListTest --warmup 2 --duration 7 --iterations 2 --parallel 2`
   - download using sas with storage-blob
     - `npm run perfstress-test:node -- StorageBlobDownloadWithSASTest --warmup 2 --duration 7 --iterations 2 --parallel 2`
   - download using sas with node-fetch
     - `npm run perfstress-test:node -- NodeFetchDownloadWithSASTest --warmup 2 --duration 7 --iterations 2 --parallel 2`
   - download using sas with core-http
     - `npm run perfstress-test:node -- CoreHTTPDownloadWithSASTest --warmup 2 --duration 7 --iterations 2 --parallel 2`
   - download using sas with core-https
     - `npm run perfstress-test:node -- CoreHTTPSDownloadWithSASTest --warmup 2 --duration 7 --iterations 2 --parallel 2`

### To run track 1 perf tests
1. Navigate to `test-utils\perfstress` folder `cd sdk\test-utils\perfstress\`
2. Build the package `rush update && rush build -t test-utils-perfstress`
3. Pack the perf package `rushx pack`
4. Navigate to `storage-blob\perfstress\track-1` folder `cd sdk\storage\storage-blob\perfstress\track-1`.
5. Install the perf package `npm i ..\..\..\..\..\test-utils\perfstress\azure-test-utils-perfstress-1.0.0.tgz`
6. Run `npm install` to get `storage-blob V10`.
7. Create a storage account and populate the .env file with `ACCOUNT_NAME` and `ACCOUNT_KEY` variables.
8. Run the tests as follows
   - download
     - `npm run perfstress-test:node -- StorageBlobDownloadTest --warmup 2 --duration 7 --iterations 2 --parallel 2`
   - upload
     - `npm run perfstress-test:node -- StorageBlobUploadTest --warmup 2 --duration 7 --iterations 2 --parallel 2`
   - list blobs
     - `npm run perfstress-test:node -- StorageBlobListTest --warmup 2 --duration 7 --iterations 2 --parallel 2`
  • Loading branch information
HarshaNalluru authored Jan 21, 2021
1 parent 3667255 commit 1d7e0e4
Show file tree
Hide file tree
Showing 22 changed files with 664 additions and 1 deletion.
2 changes: 2 additions & 0 deletions eng/.docsettings.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ omitted_paths:
- sdk/schemaregistry/README.md
- sdk/storage/*/test/README.md
- sdk/storage/storage-internal-avro/*
- sdk/storage/*/test/perfstress/track-1/*
- sdk/storage/*/test/perfstress/track-2/*
- sdk/textanalytics/*/test/README.md
- sdk/**/samples/*
- sdk/**/samples-*/*
Expand Down
5 changes: 5 additions & 0 deletions sdk/storage/storage-blob/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
"lint:fix": "eslint package.json api-extractor.json src test --ext .ts --fix",
"lint": "eslint package.json api-extractor.json src test --ext .ts -f html -o storage-blob-lintReport.html || exit 0",
"pack": "npm pack 2>&1",
"perfstress-test:node": "cross-env TS_NODE_COMPILER_OPTIONS=\"{\\\"module\\\": \\\"commonjs\\\"}\" ts-node test/perfstress/track-2/index.spec.ts",
"prebuild": "npm run clean",
"test:browser": "npm run clean && npm run build:test && npm run unit-test:browser",
"test:node": "npm run clean && npm run build:test && npm run unit-test:node",
Expand Down Expand Up @@ -128,16 +129,19 @@
"tslib": "^2.0.0"
},
"devDependencies": {
"@azure/core-https": "1.0.0-beta.1",
"@azure/dev-tool": "^1.0.0",
"@azure/eslint-plugin-azure-sdk": "^3.0.0",
"@azure/identity": "^1.1.0",
"@azure/test-utils-recorder": "^1.0.0",
"@azure/test-utils-perfstress": "^1.0.0",
"@microsoft/api-extractor": "7.7.11",
"@rollup/plugin-multi-entry": "^3.0.0",
"@rollup/plugin-replace": "^2.2.0",
"@rollup/plugin-json": "^4.0.0",
"@types/mocha": "^7.0.2",
"@types/node": "^8.0.0",
"@types/node-fetch": "^2.5.0",
"assert": "^1.4.1",
"cross-env": "^7.0.2",
"dotenv": "^8.2.0",
Expand All @@ -161,6 +165,7 @@
"karma-remap-istanbul": "^0.6.0",
"mocha": "^7.1.1",
"mocha-junit-reporter": "^1.18.0",
"node-fetch": "^2.6.0",
"nyc": "^14.0.0",
"prettier": "^1.16.4",
"puppeteer": "^3.3.0",
Expand Down
16 changes: 16 additions & 0 deletions sdk/storage/storage-blob/test/perfstress/track-1/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
### Guide

1. Navigate to `test-utils\perfstress` folder `cd sdk\test-utils\perfstress\`
2. Build the package `rush update && rush build -t test-utils-perfstress`
3. Pack the perf package `rushx pack`
4. Navigate to `storage-blob\perfstress\track-1` folder `cd sdk\storage\storage-blob\perfstress\track-1`.
5. Install the perf package `npm i ..\..\..\..\..\test-utils\perfstress\azure-test-utils-perfstress-1.0.0.tgz`
6. Run `npm install` to get `storage-blob V10`.
7. Create a storage account and populate the .env file with `ACCOUNT_NAME` and `ACCOUNT_KEY` variables.
8. Run the tests as follows
- download
- `npm run perfstress-test:node -- StorageBlobDownloadTest --warmup 2 --duration 7 --iterations 2 --parallel 2`
- upload
- `npm run perfstress-test:node -- StorageBlobUploadTest --warmup 2 --duration 7 --iterations 2 --parallel 2`
- list blobs
- `npm run perfstress-test:node -- StorageBlobListTest --warmup 2 --duration 7 --iterations 2 --parallel 2`
48 changes: 48 additions & 0 deletions sdk/storage/storage-blob/test/perfstress/track-1/download.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import { generateUuid } from "@azure/core-http";
import { Aborter, BlobURL, BlockBlobURL } from "@azure/storage-blob";
import { PerfStressOptionDictionary, drainStream } from "@azure/test-utils-perfstress";
import { StorageBlobTest } from "./storageTest.spec";

interface StorageBlobDownloadTestOptions {
size: number;
}

export class StorageBlobDownloadTest extends StorageBlobTest<StorageBlobDownloadTestOptions> {
public options: PerfStressOptionDictionary<StorageBlobDownloadTestOptions> = {
size: {
required: true,
description: "Size in bytes",
shortName: "sz",
longName: "size",
defaultValue: 10240
}
};

static blobName = generateUuid();
blockBlobClient: BlockBlobURL;

constructor() {
super();
this.blockBlobClient = BlockBlobURL.fromBlobURL(
BlobURL.fromContainerURL(this.containerClient, StorageBlobDownloadTest.blobName)
);
}

public async globalSetup() {
await super.globalSetup();
// Create a blob
await this.blockBlobClient.upload(
Aborter.none,
Buffer.alloc(this.parsedOptions.size.value!),
this.parsedOptions.size.value!
);
}

async runAsync(): Promise<void> {
const downloadResponse = await this.blockBlobClient.download(Aborter.none, 0);
await drainStream(downloadResponse.readableStreamBody!);
}
}
15 changes: 15 additions & 0 deletions sdk/storage/storage-blob/test/perfstress/track-1/index.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import { PerfStressProgram, selectPerfStressTest } from "@azure/test-utils-perfstress";
import { StorageBlobDownloadTest } from "./download.spec";
import { StorageBlobUploadTest } from "./upload.spec";
import { StorageBlobListTest } from "./listBlobs.spec";

console.log("=== Starting the perfStress test ===");

const perfStressProgram = new PerfStressProgram(
selectPerfStressTest([StorageBlobDownloadTest, StorageBlobUploadTest, StorageBlobListTest])
);

perfStressProgram.run();
45 changes: 45 additions & 0 deletions sdk/storage/storage-blob/test/perfstress/track-1/listBlobs.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import { generateUuid } from "@azure/core-http";
import { Aborter, BlockBlobURL } from "@azure/storage-blob";
import { executeParallel, PerfStressOptionDictionary } from "@azure/test-utils-perfstress";
import { StorageBlobTest } from "./storageTest.spec";

interface StorageBlobListTestOptions {
count: number;
}

export class StorageBlobListTest extends StorageBlobTest<StorageBlobListTestOptions> {
public options: PerfStressOptionDictionary<StorageBlobListTestOptions> = {
count: {
required: true,
description: "Number of blobs to be listed",
longName: "count",
defaultValue: 10
}
};

public async globalSetup() {
await super.globalSetup();
await executeParallel(
async (count: number, parallelIndex: number) => {
const blockBlobClient = BlockBlobURL.fromContainerURL(this.containerClient, generateUuid());
blockBlobClient.upload(Aborter.none, Buffer.alloc(0), 0);
console.log(`[` + parallelIndex + `] ` + count);
},
this.parsedOptions.count.value!,
32
);
}

async runAsync(): Promise<void> {
// List blobs
let marker = undefined;
do {
const segmentResponse = await this.containerClient.listBlobFlatSegment(Aborter.none, marker);
for (const _ of segmentResponse.segment.blobItems) {
}
marker = segmentResponse.nextMarker;
} while (marker);
}
}
18 changes: 18 additions & 0 deletions sdk/storage/storage-blob/test/perfstress/track-1/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"name": "track-1",
"version": "1.0.0",
"description": "",
"main": "index.js",
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"@azure/storage-blob": "^10.5.0",
"@azure/test-utils-perfstress": "file:../../../../../test-utils/perfstress/azure-test-utils-perfstress-1.0.0.tgz",
"@types/uuid": "^8.3.0",
"uuid": "^8.3.2"
},
"scripts": {
"perfstress-test:node": "ts-node index.spec.ts"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import { generateUuid } from "@azure/core-http";
import {
Aborter,
ContainerURL,
ServiceURL,
SharedKeyCredential,
StorageURL
} from "@azure/storage-blob";
import { PerfStressTest, getEnvVar } from "@azure/test-utils-perfstress";

// Expects the .env file at the same level as the "test" folder
import * as dotenv from "dotenv";
dotenv.config({ path: "../../../.env" });

export abstract class StorageBlobTest<TOptions> extends PerfStressTest<TOptions> {
blobServiceClient: ServiceURL;
containerClient: ContainerURL;
static containerName = generateUuid();

constructor() {
super();
const connectionString = getEnvVar("STORAGE_CONNECTION_STRING");
const accountName = getValueInConnectionString(connectionString, "AccountName");
const accountKey = getValueInConnectionString(connectionString, "AccountKey");

const sharedKeyCredential = new SharedKeyCredential(accountName, accountKey);
this.blobServiceClient = new ServiceURL(
`https://${accountName}.blob.core.windows.net`,
StorageURL.newPipeline(sharedKeyCredential)
);
this.containerClient = ContainerURL.fromServiceURL(
this.blobServiceClient,
StorageBlobTest.containerName
);
}

public async globalSetup() {
await this.containerClient.create(Aborter.none);
}

public async globalCleanup() {
await this.containerClient.delete(Aborter.none);
}
}

export function getValueInConnectionString(
connectionString: string,
argument: "AccountName" | "AccountKey"
) {
const elements = connectionString.split(";");
for (const element of elements) {
if (element.trim().startsWith(argument)) {
return element.trim().match(argument + "=(.*)")![1];
}
}
return "";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"compilerOptions": {
"module": "commonjs"
}
}
41 changes: 41 additions & 0 deletions sdk/storage/storage-blob/test/perfstress/track-1/upload.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import { generateUuid } from "@azure/core-http";
import { Aborter, BlockBlobURL } from "@azure/storage-blob";
import { PerfStressOptionDictionary } from "@azure/test-utils-perfstress";

// Expects the .env file at the same level as the "test" folder
import * as dotenv from "dotenv";
import { StorageBlobTest } from "./storageTest.spec";
dotenv.config({ path: "../../../.env" });

interface StorageBlobUploadTestOptions {
size: number;
}

export class StorageBlobUploadTest extends StorageBlobTest<StorageBlobUploadTestOptions> {
blobName: string;
blockBlobClient: BlockBlobURL;
buffer: Buffer;
public options: PerfStressOptionDictionary<StorageBlobUploadTestOptions> = {
size: {
required: true,
description: "Size in bytes",
shortName: "sz",
longName: "size",
defaultValue: 10240
}
};

constructor() {
super();
this.blobName = generateUuid();
this.blockBlobClient = BlockBlobURL.fromContainerURL(this.containerClient, this.blobName);
this.buffer = Buffer.alloc(this.parsedOptions.size.value!);
}

async runAsync(): Promise<void> {
await this.blockBlobClient.upload(Aborter.none, this.buffer, this.parsedOptions.size.value!);
}
}
23 changes: 23 additions & 0 deletions sdk/storage/storage-blob/test/perfstress/track-2/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
### Guide

1. Build the storage-blob package `rush build -t storage-blob`.
2. Navigate to `storage-blob` folder `cd sdk\storage\storage-blob\`.
3. Create a storage account and populate the .env file at `storage\storage-blob` folder with `STORAGE_CONNECTION_STRING` variables.
4. Run the tests as follows

- download
- `npm run perfstress-test:node -- StorageBlobDownloadTest --warmup 2 --duration 7 --iterations 2 --parallel 2`
- upload
- `npm run perfstress-test:node -- StorageBlobUploadTest --warmup 2 --duration 7 --iterations 2 --parallel 2`
- upload file
- `npm run perfstress-test:node -- StorageBlobUploadFileTest --warmup 2 --duration 7 --iterations 2 --parallel 2`
- list blobs
- `npm run perfstress-test:node -- StorageBlobListTest --warmup 2 --duration 7 --iterations 2 --parallel 2`
- download using sas with storage-blob
- `npm run perfstress-test:node -- StorageBlobDownloadWithSASTest --warmup 2 --duration 7 --iterations 2 --parallel 2`
- download using sas with node-fetch
- `npm run perfstress-test:node -- NodeFetchDownloadWithSASTest --warmup 2 --duration 7 --iterations 2 --parallel 2`
- download using sas with core-http
- `npm run perfstress-test:node -- CoreHTTPDownloadWithSASTest --warmup 2 --duration 7 --iterations 2 --parallel 2`
- download using sas with core-https
- `npm run perfstress-test:node -- CoreHTTPSDownloadWithSASTest --warmup 2 --duration 7 --iterations 2 --parallel 2`
35 changes: 35 additions & 0 deletions sdk/storage/storage-blob/test/perfstress/track-2/core-http.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import { StorageBlobDownloadWithSASTest } from "./dowloadWithSAS.spec";
import { ServiceClient, WebResource } from "@azure/core-http";
import { drainStream } from "@azure/test-utils-perfstress";

export class CoreHTTPDownloadWithSASTest extends StorageBlobDownloadWithSASTest {
client: ServiceClient;
webResource: WebResource;
constructor() {
super();
this.client = new ServiceClient();
this.webResource = new WebResource(
this.sasUrl,
undefined,
undefined,
undefined,
undefined,
true, // streamResponseBody
undefined,
undefined,
undefined,
undefined,
undefined,
undefined,
true // keepAlive
);
}

async runAsync(): Promise<void> {
const response = await this.client.sendRequest(this.webResource);
await drainStream(response.readableStreamBody!);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import { StorageBlobDownloadWithSASTest } from "./dowloadWithSAS.spec";
import { DefaultHttpsClient, createPipelineRequest, PipelineRequest } from "@azure/core-https";
import { drainStream } from "@azure/test-utils-perfstress";

export class CoreHTTPSDownloadWithSASTest extends StorageBlobDownloadWithSASTest {
client: DefaultHttpsClient;
request: PipelineRequest<any>;
constructor() {
super();
this.client = new DefaultHttpsClient();
this.request = createPipelineRequest({
url: this.sasUrl,
streamResponseBody: true,
keepAlive: true
});
}

async runAsync(): Promise<void> {
const response = await this.client.sendRequest(this.request);
await drainStream(response.readableStreamBody!);
}
}
Loading

0 comments on commit 1d7e0e4

Please sign in to comment.