Skip to content

Commit 63b1e56

Browse files
committed
Allow BlazorWasm benchmark driver to perform stress runs
Adds an option that allows running the driver in a loop until timeout expires
1 parent 63e8089 commit 63b1e56

File tree

6 files changed

+54
-29
lines changed

6 files changed

+54
-29
lines changed

src/Components/benchmarkapps/Wasm.Performance/Driver/BenchmarkResultsStartup.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public void Configure(IApplicationBuilder app)
2929
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
3030
});
3131
await context.Response.WriteAsync("OK");
32-
Program.SetBenchmarkResult(result);
32+
Program.BenchmarkResultTask.TrySetResult(result);
3333
});
3434
}
3535
}

src/Components/benchmarkapps/Wasm.Performance/Driver/Program.cs

Lines changed: 45 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,7 @@
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33

44
using System;
5-
using System.Collections.Generic;
65
using System.IO;
7-
using System.IO.Compression;
86
using System.Linq;
97
using System.Reflection;
108
using System.Runtime.ExceptionServices;
@@ -23,51 +21,74 @@ namespace Wasm.Performance.Driver
2321
{
2422
public class Program
2523
{
26-
static readonly TimeSpan Timeout = TimeSpan.FromMinutes(3);
27-
static TaskCompletionSource<BenchmarkResult> benchmarkResult = new TaskCompletionSource<BenchmarkResult>();
24+
internal static TaskCompletionSource<BenchmarkResult> BenchmarkResultTask;
2825

2926
public static async Task<int> Main(string[] args)
3027
{
31-
var seleniumPort = 4444;
28+
// This cancellation token manages the timeout for the stress run.
29+
// By default the driver executes and reports a single Benchmark run. For stress runs,
30+
// we'll pass in the duration to execute the runs in milliseconds. This will cause this driver
31+
// to repeat executions for the duration specified.
32+
var stressRunCancellation = new CancellationToken(canceled: true);
3233
if (args.Length > 0)
3334
{
34-
if (!int.TryParse(args[0], out seleniumPort))
35+
if (!int.TryParse(args[0], out var stressRunSeconds))
3536
{
36-
Console.Error.WriteLine("Usage Driver <selenium-port>");
37+
Console.Error.WriteLine("Usage Driver <stress-run-duration>");
3738
return 1;
3839
}
40+
41+
if (stressRunSeconds > 0)
42+
{
43+
var stressRunDuration = TimeSpan.FromSeconds(stressRunSeconds);
44+
Console.WriteLine($"Stress run duration: {stressRunDuration}.");
45+
stressRunCancellation = new CancellationTokenSource(stressRunDuration).Token;
46+
}
3947
}
4048

4149
// This write is required for the benchmarking infrastructure.
4250
Console.WriteLine("Application started.");
4351

44-
var cancellationToken = new CancellationTokenSource(Timeout);
45-
cancellationToken.Token.Register(() => benchmarkResult.TrySetException(new TimeoutException($"Timed out after {Timeout}")));
46-
47-
using var browser = await Selenium.CreateBrowser(seleniumPort, cancellationToken.Token);
52+
using var browser = await Selenium.CreateBrowser(default);
4853
using var testApp = StartTestApp();
4954
using var benchmarkReceiver = StartBenchmarkResultReceiver();
50-
5155
var testAppUrl = GetListeningUrl(testApp);
5256
var receiverUrl = GetListeningUrl(benchmarkReceiver);
53-
5457
Console.WriteLine($"Test app listening at {testAppUrl}.");
5558

56-
var launchUrl = $"{testAppUrl}?resultsUrl={UrlEncoder.Default.Encode(receiverUrl)}#automated";
57-
browser.Url = launchUrl;
58-
browser.Navigate();
59+
var first = true;
60+
do
61+
{
62+
BenchmarkResultTask = new TaskCompletionSource<BenchmarkResult>();
63+
var timeForEachRun = TimeSpan.FromMinutes(3);
64+
using var runCancellationToken = new CancellationTokenSource(timeForEachRun);
65+
runCancellationToken.Token.Register(() => BenchmarkResultTask.TrySetException(new TimeoutException($"Timed out after {timeForEachRun}")));
66+
67+
if (first)
68+
{
69+
first = false;
70+
var launchUrl = $"{testAppUrl}?resultsUrl={UrlEncoder.Default.Encode(receiverUrl)}#automated";
71+
browser.Url = launchUrl;
72+
browser.Navigate();
73+
}
74+
else
75+
{
76+
browser.FindElementById("runAll").Click();
77+
}
78+
79+
var results = await BenchmarkResultTask.Task;
80+
FormatAsBenchmarksOutput(results);
5981

60-
FormatAsBenchmarksOutput(benchmarkResult.Task.Result);
82+
if (!stressRunCancellation.IsCancellationRequested)
83+
{
84+
Console.WriteLine("!Hello world!");
85+
}
86+
} while (!stressRunCancellation.IsCancellationRequested);
6187

6288
Console.WriteLine("Done executing benchmark");
6389
return 0;
6490
}
6591

66-
internal static void SetBenchmarkResult(BenchmarkResult result)
67-
{
68-
benchmarkResult.TrySetResult(result);
69-
}
70-
7192
private static void FormatAsBenchmarksOutput(BenchmarkResult benchmarkResult)
7293
{
7394
// Sample of the the format: https://github.com/aspnet/Benchmarks/blob/e55f9e0312a7dd019d1268c1a547d1863f0c7237/src/Benchmarks/Program.cs#L51-L67
@@ -184,9 +205,9 @@ static void RunInBackgroundThread(Action action)
184205
isDone.Set();
185206
});
186207

187-
if (!isDone.WaitOne(Timeout))
208+
if (!isDone.WaitOne(TimeSpan.FromSeconds(30)))
188209
{
189-
throw new TimeoutException("Timed out waiting for: " + action);
210+
throw new TimeoutException("Timed out waiting to start the host");
190211
}
191212

192213
if (edi != null)

src/Components/benchmarkapps/Wasm.Performance/Driver/Selenium.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (c) .NET Foundation. All rights reserved.
1+
// Copyright (c) .NET Foundation. All rights reserved.
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33

44
using System;
@@ -15,6 +15,7 @@ namespace Wasm.Performance.Driver
1515
{
1616
class Selenium
1717
{
18+
const int SeleniumPort = 4444;
1819
static bool RunHeadlessBrowser = true;
1920
static bool PoolForBrowserLogs = true;
2021

@@ -55,9 +56,9 @@ private static async ValueTask<Uri> WaitForServerAsync(int port, CancellationTok
5556
throw new Exception($"Unable to connect to selenium-server at {uri}");
5657
}
5758

58-
public static async Task<RemoteWebDriver> CreateBrowser(int port, CancellationToken cancellationToken)
59+
public static async Task<RemoteWebDriver> CreateBrowser(CancellationToken cancellationToken)
5960
{
60-
var uri = await WaitForServerAsync(port, cancellationToken);
61+
var uri = await WaitForServerAsync(SeleniumPort, cancellationToken);
6162

6263
var options = new ChromeOptions();
6364

src/Components/benchmarkapps/Wasm.Performance/dockerfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build
22

3+
ENV StressRunDuration=0
34
ARG DEBIAN_FRONTEND=noninteractive
45

56
# Setup for nodejs
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#!/usr/bin/env bash
22

33
/opt/bin/start-selenium-standalone.sh&
4-
./Wasm.Performance.Driver
4+
./Wasm.Performance.Driver $StressRunDuration
55

src/Components/benchmarkapps/Wasm.Performance/local.dockerfile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
FROM selenium/standalone-chrome:3.141.59-mercury as final
22

3+
ENV StressRunDuration=0
4+
35
WORKDIR /app
46
COPY ./Driver/bin/Release/netcoreapp3.1/linux-x64/publish ./
57
COPY ./exec.sh ./

0 commit comments

Comments
 (0)