From 3bb63b221385dc19ec77d46c54e02e2fb0a58c63 Mon Sep 17 00:00:00 2001 From: Harsha Nalluru Date: Mon, 12 Jun 2023 13:44:05 -0700 Subject: [PATCH] [Event Hubs] Update stress and perf tests post "prefetch feature" testing (#26095) ## Updates to the tests following #26065 1. default test duration is set to 2 days for stress tests 2. Added a new "log-median-batch-size" option for the perf test - `log-median-batch-size` is a boolean that logs more information related to the batch size, such as median, max, average, etc. - It can be useful when relevant code is updated. - Being introduced in the perf test when the prefetch feature was added to Event Hubs. --------- Co-authored-by: Deyaaeldeen Almahallawi --- .../stress/app/src/scenarioCheckpointStore.ts | 2 +- .../stress/app/src/scenarioGetRuntimeProps.ts | 2 +- .../test/stress/app/src/scenarioNoActivity.ts | 10 ++--- .../test/stress/generatedValues.yaml | 17 +++++++++ .../event-hubs/test/subscribe.spec.ts | 38 +++++++++++++++++++ 5 files changed, 60 insertions(+), 9 deletions(-) create mode 100644 sdk/eventhub/event-hubs/test/stress/generatedValues.yaml diff --git a/sdk/eventhub/event-hubs/test/stress/app/src/scenarioCheckpointStore.ts b/sdk/eventhub/event-hubs/test/stress/app/src/scenarioCheckpointStore.ts index 5135b99e8b70..0597caa25244 100644 --- a/sdk/eventhub/event-hubs/test/stress/app/src/scenarioCheckpointStore.ts +++ b/sdk/eventhub/event-hubs/test/stress/app/src/scenarioCheckpointStore.ts @@ -16,7 +16,7 @@ interface scenarioCheckpointStoreOptions { function sanitizeOptions(args: string[]): Required { const options = parsedArgs(args); return { - testDurationInMs: options.testDurationInMs || 20 * 24 * 60 * 60 * 1000, // Default = 20 days + testDurationInMs: options.testDurationInMs || 2 * 24 * 60 * 60 * 1000, // Default = 2 days }; } diff --git a/sdk/eventhub/event-hubs/test/stress/app/src/scenarioGetRuntimeProps.ts b/sdk/eventhub/event-hubs/test/stress/app/src/scenarioGetRuntimeProps.ts index caa2de84bbcb..df5c60c7bccf 100644 --- a/sdk/eventhub/event-hubs/test/stress/app/src/scenarioGetRuntimeProps.ts +++ b/sdk/eventhub/event-hubs/test/stress/app/src/scenarioGetRuntimeProps.ts @@ -13,7 +13,7 @@ interface scenarioGetRuntimePropertiesOptions { function sanitizeOptions(args: string[]): Required { const options = parsedArgs(args); return { - testDurationInMs: options.testDurationInMs || 10 * 60 * 60 * 1000, // Default = 10 hrs + testDurationInMs: options.testDurationInMs || 2 * 24 * 60 * 60 * 1000, // Default = 2 days }; } diff --git a/sdk/eventhub/event-hubs/test/stress/app/src/scenarioNoActivity.ts b/sdk/eventhub/event-hubs/test/stress/app/src/scenarioNoActivity.ts index 8f88f4af825d..69f83d2670bb 100644 --- a/sdk/eventhub/event-hubs/test/stress/app/src/scenarioNoActivity.ts +++ b/sdk/eventhub/event-hubs/test/stress/app/src/scenarioNoActivity.ts @@ -2,14 +2,10 @@ // Licensed under the MIT license. import { delay } from "@azure/core-util"; -import { - EventHubsStressTester, - createEventHubsConsumerClient, - createEventHubsProducerClient, - defaultClientAppInsights, -} from "./eventHubsStressTester"; +import { EventHubsStressTester, defaultClientAppInsights } from "./eventHubsStressTester"; import parsedArgs from "minimist"; import { Subscription } from "@azure/event-hubs"; +import { createEventHubsConsumerClient, createEventHubsProducerClient } from "./utils"; interface ScenarioNoActivityOptions { testDurationInMs?: number; @@ -19,7 +15,7 @@ interface ScenarioNoActivityOptions { function sanitizeOptions(args: string[]): Required { const options = parsedArgs(args); return { - testDurationInMs: options.testDurationInMs || 10 * 60 * 60 * 1000, // Default = 10 hrs + testDurationInMs: options.testDurationInMs || 2 * 24 * 60 * 60 * 1000, // Default = 2 days maxBatchSize: options.maxBatchSize || 100, }; } diff --git a/sdk/eventhub/event-hubs/test/stress/generatedValues.yaml b/sdk/eventhub/event-hubs/test/stress/generatedValues.yaml new file mode 100644 index 000000000000..c52c2bee7964 --- /dev/null +++ b/sdk/eventhub/event-hubs/test/stress/generatedValues.yaml @@ -0,0 +1,17 @@ +scenarios: +- testTarget: scenarioNoActivity + image: Dockerfile + Scenario: node18-noActivity + memory: 1.5Gi + imageTag: stresspgs7b6dif73rup6.azurecr.io/harshan-eh-prefetch/jseh/dockerfile:harshanalluru +- testTarget: scenarioCheckpointStore + image: Dockerfile + Scenario: node18-checkpointStore + memory: 1.5Gi + imageTag: stresspgs7b6dif73rup6.azurecr.io/harshan-eh-prefetch/jseh/dockerfile:harshanalluru +- testTarget: scenarioGetRuntimeProps + image: Dockerfile + Scenario: node18-getRuntimeProps + memory: 1.5Gi + imageTag: stresspgs7b6dif73rup6.azurecr.io/harshan-eh-prefetch/jseh/dockerfile:harshanalluru + diff --git a/sdk/eventhub/perf-tests/event-hubs/test/subscribe.spec.ts b/sdk/eventhub/perf-tests/event-hubs/test/subscribe.spec.ts index 466059b8b50b..19a2696572bb 100644 --- a/sdk/eventhub/perf-tests/event-hubs/test/subscribe.spec.ts +++ b/sdk/eventhub/perf-tests/event-hubs/test/subscribe.spec.ts @@ -16,6 +16,12 @@ interface ReceiverOptions { "event-size-in-bytes": number; partitions: number; "max-batch-size": number; + /** + * Logs more information related to the batch size, such as median, max, average, etc + * Useful when relevant code is updated + * Introduced when prefetch feature was added to Event Hubs + */ + "log-median-batch-size": boolean } const connectionString = getEnvVar("EVENTHUB_CONNECTION_STRING"); @@ -27,6 +33,8 @@ const consumer = new EventHubConsumerClient(consumerGroup, connectionString, eve export class SubscribeTest extends EventPerfTest { receiver: EventHubConsumerClient; subscriber: { close: () => Promise } | undefined; + callbackCallsCount = 0; + messagesPerBatch: Array = []; options: PerfOptionDictionary = { "number-of-events": { @@ -57,6 +65,11 @@ export class SubscribeTest extends EventPerfTest { longName: "max-batch-size", defaultValue: 100, }, + "log-median-batch-size": { + required: false, + description: "Logs more information related to the batch size, such as median, max, average, etc", + defaultValue: false, + } }; constructor() { @@ -83,6 +96,10 @@ export class SubscribeTest extends EventPerfTest { for (const _event of events) { this.eventRaised(); } + if (this.parsedOptions["log-median-batch-size"].value) { + this.callbackCallsCount++; + this.messagesPerBatch.push(events.length); + } }, processError: async (error: Error | MessagingError, _context: PartitionContext) => { this.errorRaised(error); @@ -102,6 +119,12 @@ export class SubscribeTest extends EventPerfTest { async globalCleanup(): Promise { await consumer.close(); + // The following might just be noise if we don't think there are related changes to the code + if (this.parsedOptions["log-median-batch-size"].value) { + console.log(`\tBatch count: ${this.callbackCallsCount}, Batch count per sec: ${this.callbackCallsCount / this.parsedOptions.duration.value}`); + console.log(`\tmessagesPerBatch: ${this.messagesPerBatch}`); + console.log(`\tmessagesPerBatch... median: ${median(this.messagesPerBatch)}, avg: ${this.messagesPerBatch.reduce((a, b) => a + b, 0) / this.messagesPerBatch.length}, max: ${Math.max(...this.messagesPerBatch)}, min: ${Math.min(...this.messagesPerBatch)}`); + } } } @@ -138,3 +161,18 @@ async function sendBatch( await producer.close(); } + +function median(values: number[]) { + if (values.length === 0) throw new Error("No inputs while calculating median"); + + values.sort(function (a, b) { + return a - b; + }); + + const half = Math.floor(values.length / 2); + + if (values.length % 2) + return values[half]; + + return (values[half - 1] + values[half]) / 2.0; +}