Skip to content

Commit 62ece1b

Browse files
Fix Blazor WebAssembly perf benchmarks (#56811)
1 parent 67feeaa commit 62ece1b

File tree

11 files changed

+57
-242
lines changed

11 files changed

+57
-242
lines changed

eng/Versions.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,7 @@
310310
<NewtonsoftJsonVersion>13.0.3</NewtonsoftJsonVersion>
311311
<NSwagApiDescriptionClientVersion>13.0.4</NSwagApiDescriptionClientVersion>
312312
<PhotinoNETVersion>2.5.2</PhotinoNETVersion>
313-
<MicrosoftPlaywrightVersion>1.28.0</MicrosoftPlaywrightVersion>
313+
<MicrosoftPlaywrightVersion>1.45.1</MicrosoftPlaywrightVersion>
314314
<PollyExtensionsHttpVersion>3.0.0</PollyExtensionsHttpVersion>
315315
<PollyVersion>7.2.4</PollyVersion>
316316
<SeleniumSupportVersion>4.22.0</SeleniumSupportVersion>

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

Lines changed: 35 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,14 @@
88
using System.Text.Json;
99
using Microsoft.AspNetCore.Hosting.Server;
1010
using Microsoft.AspNetCore.Hosting.Server.Features;
11-
using OpenQA.Selenium;
12-
using DevHostServerProgram = Microsoft.AspNetCore.Components.WebAssembly.DevServer.Server.Program;
11+
using Microsoft.Playwright;
1312

1413
namespace Wasm.Performance.Driver;
1514

1615
public class Program
1716
{
17+
private const bool RunHeadless = true;
18+
1819
internal static TaskCompletionSource<BenchmarkResult> BenchmarkResultTask;
1920

2021
public static async Task<int> Main(string[] args)
@@ -51,7 +52,18 @@ public static async Task<int> Main(string[] args)
5152
// This write is required for the benchmarking infrastructure.
5253
Console.WriteLine("Application started.");
5354

54-
using var browser = await Selenium.CreateBrowser(default, captureBrowserMemory: isStressRun);
55+
var browserArgs = new List<string>();
56+
if (isStressRun)
57+
{
58+
browserArgs.Add("--enable-precise-memory-info");
59+
}
60+
61+
using var playwright = await Playwright.CreateAsync();
62+
await using var browser = await playwright.Chromium.LaunchAsync(new()
63+
{
64+
Headless = RunHeadless,
65+
Args = browserArgs,
66+
});
5567
using var testApp = StartTestApp();
5668
using var benchmarkReceiver = StartBenchmarkResultReceiver();
5769
var testAppUrl = GetListeningUrl(testApp);
@@ -67,19 +79,20 @@ public static async Task<int> Main(string[] args)
6779
var timeForEachRun = TimeSpan.FromMinutes(3);
6880

6981
var launchUrl = $"{testAppUrl}?resultsUrl={UrlEncoder.Default.Encode(receiverUrl)}#automated";
70-
browser.Url = launchUrl;
71-
browser.Navigate();
82+
var page = await browser.NewPageAsync();
83+
await page.GotoAsync(launchUrl);
84+
page.Console += WriteBrowserConsoleMessage;
7285

7386
do
7487
{
7588
BenchmarkResultTask = new TaskCompletionSource<BenchmarkResult>();
7689
using var runCancellationToken = new CancellationTokenSource(timeForEachRun);
77-
using var registration = runCancellationToken.Token.Register(() =>
90+
using var registration = runCancellationToken.Token.Register(async () =>
7891
{
79-
string exceptionMessage = $"Timed out after {timeForEachRun}.";
92+
var exceptionMessage = $"Timed out after {timeForEachRun}.";
8093
try
8194
{
82-
var innerHtml = browser.FindElement(By.CssSelector(":first-child")).GetAttribute("innerHTML");
95+
var innerHtml = await page.GetAttributeAsync(":first-child", "innerHTML");
8396
exceptionMessage += Environment.NewLine + "Browser state: " + Environment.NewLine + innerHtml;
8497
}
8598
catch
@@ -107,6 +120,11 @@ public static async Task<int> Main(string[] args)
107120
return 0;
108121
}
109122

123+
private static void WriteBrowserConsoleMessage(object sender, IConsoleMessage message)
124+
{
125+
Console.WriteLine($"[Browser Log]: {message.Text}");
126+
}
127+
110128
private static void FormatAsBenchmarksOutput(BenchmarkResult benchmarkResult, bool includeMetadata, bool isStressRun)
111129
{
112130
// Sample of the the format: https://github.com/aspnet/Benchmarks/blob/e55f9e0312a7dd019d1268c1a547d1863f0c7237/src/Benchmarks/Program.cs#L51-L67
@@ -252,31 +270,20 @@ static void PrettyPrint(BenchmarkResult benchmarkResult)
252270
}
253271
}
254272

255-
static IHost StartTestApp()
273+
static WebApplication StartTestApp()
256274
{
257-
var args = new[]
258-
{
259-
"--urls", "http://127.0.0.1:0",
260-
"--applicationpath", typeof(TestApp.Program).Assembly.Location,
261-
#if DEBUG
262-
"--contentroot",
263-
Path.GetFullPath(typeof(Program).Assembly.GetCustomAttributes<AssemblyMetadataAttribute>()
264-
.First(f => f.Key == "TestAppLocatiion")
265-
.Value)
266-
#endif
267-
};
268-
269-
var host = DevHostServerProgram.BuildWebHost(args);
270-
RunInBackgroundThread(host.Start);
271-
return host;
275+
string[] args = ["--urls", "http://127.0.0.1:0"];
276+
var app = WebApplication.Create(args);
277+
app.MapStaticAssets();
278+
app.MapFallbackToFile("index.html");
279+
280+
RunInBackgroundThread(app.Start);
281+
return app;
272282
}
273283

274284
static IHost StartBenchmarkResultReceiver()
275285
{
276-
var args = new[]
277-
{
278-
"--urls", "http://127.0.0.1:0",
279-
};
286+
string[] args = ["--urls", "http://127.0.0.1:0"];
280287

281288
var host = Host.CreateDefaultBuilder(args)
282289
.ConfigureWebHostDefaults(builder => builder.UseStartup<BenchmarkDriverStartup>())

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

Lines changed: 0 additions & 136 deletions
This file was deleted.

src/Components/benchmarkapps/Wasm.Performance/Driver/Wasm.Performance.Driver.csproj

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,32 +8,16 @@
88
<!-- WebDriver is not strong-named, so this test project cannot be strong named either. -->
99
<SignAssembly>false</SignAssembly>
1010
<IsTestAssetProject>true</IsTestAssetProject>
11-
<RuntimeIdentifier Condition=" '$(DotNetBuildSourceOnly)' != 'true' ">linux-x64</RuntimeIdentifier>
12-
<SelfContained Condition=" '$(DotNetBuildSourceOnly)' != 'true' ">true</SelfContained>
1311
<Nullable>annotations</Nullable>
1412
</PropertyGroup>
1513

1614
<ItemGroup>
1715
<Reference Include="Microsoft.AspNetCore" />
1816
<Reference Include="Microsoft.AspNetCore.Cors" />
1917
<Reference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" />
20-
<Reference Include="Selenium.Support" />
21-
<Reference Include="Selenium.WebDriver" />
18+
<Reference Include="Microsoft.Playwright" Condition="'$(IsPlaywrightAvailable)' == 'true'" />
19+
<Reference Include="Microsoft.Playwright" ExcludeAssets="build" Condition="'$(IsPlaywrightAvailable)' != 'true'" />
2220
<ProjectReference Include="..\TestApp\Wasm.Performance.TestApp.csproj" />
2321
</ItemGroup>
2422

25-
<ItemGroup>
26-
<Compile Include="..\..\..\WebAssembly\DevServer\src\Server\*.cs" />
27-
</ItemGroup>
28-
29-
<Target Name="_AddTestProjectMetadataAttributes" BeforeTargets="BeforeCompile">
30-
<ItemGroup>
31-
<AssemblyAttribute
32-
Include="System.Reflection.AssemblyMetadataAttribute">
33-
<_Parameter1>TestAppLocatiion</_Parameter1>
34-
<_Parameter2>$(MSBuildThisFileDirectory)..\TestApp\</_Parameter2>
35-
</AssemblyAttribute>
36-
</ItemGroup>
37-
</Target>
38-
3923
</Project>

src/Components/benchmarkapps/Wasm.Performance/README.md

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,16 @@ See https://github.com/aspnet/Benchmarks#benchmarks for usage guidance on using
55

66
### Running the benchmarks
77

8-
The TestApp is a regular BlazorWASM project and can be run using `dotnet run`. The Driver is an app that connects against an existing Selenium server, and speaks the Benchmark protocol. You generally do not need to run the Driver locally, but if you were to do so, you can either start a selenium-server instance and run using `dotnet run [<selenium-server-port>]` or run it inside a Linux-based docker container.
8+
The TestApp is a regular BlazorWASM project and can be run using `dotnet run`. The Driver is an app that uses Playwright to launch a browser and run the test app, reporting benchmark results in Crank's protocol format. You generally do not need to run the Driver locally, you can do so if needed via `dotnet run`.
99

10-
Here are the commands you would need to run it locally inside docker:
11-
12-
1. `dotnet publish -c Release Driver/Wasm.Performance.Driver.csproj`
13-
2. `docker build -t blazor-local -f ./local.dockerfile . `
14-
3. `docker run -it blazor-local`
15-
16-
To run the benchmark app in the Benchmark server, run
10+
The benchmark app can also be run using [Crank](https://github.com/dotnet/crank?tab=readme-ov-file). To run the benchmark app in the Benchmark server, follow the Crank installation steps and then run:
1711

1812
```
19-
dotnet run -- --config aspnetcore/src/Components/benchmarkapps/Wasm.Performance/benchmarks.compose.json application.endpoints <BenchmarkServerUri> --scenario blazorwasmbenchmark
13+
crank --config https://github.com/dotnet/aspnetcore/blob/main/src/Components/benchmarkapps/Wasm.Performance/benchmarks.compose.json?raw=true --config https://github.com/aspnet/Benchmarks/blob/main/scenarios/aspnet.profiles.yml?raw=true --scenario blazorwasmbenchmark --profile aspnet-perf-lin
2014
```
2115

2216
If you have local changes that you'd like to benchmark, the easiest way is to push your local changes and tell the server to use your branch:
2317

2418
```
25-
dotnet run -- --config aspnetcore/src/Components/benchmarkapps/Wasm.Performance/benchmarks.compose.json application.endpoints <BenchmarkServerUri> --scenario blazorwasmbenchmark --application.buildArguments "gitBranch=mylocalchanges"
26-
```
19+
crank --config https://github.com/dotnet/aspnetcore/blob/main/src/Components/benchmarkapps/Wasm.Performance/benchmarks.compose.json?raw=true --config https://github.com/aspnet/Benchmarks/blob/main/scenarios/aspnet.profiles.yml?raw=true --scenario blazorwasmbenchmark --profile aspnet-perf-lin --application.buildArguments gitBranch=myLocalChanges --application.source.branchOrCommit myLocalChanges
20+
```

src/Components/benchmarkapps/Wasm.Performance/TestApp/Wasm.Performance.TestApp.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<IsTestAssetProject>true</IsTestAssetProject>
66
<!--
77
Chrome in docker appears to run in to cache corruption issues when the cache is read multiple times over.
8-
Clien caching isn't part of our performance measurement, so we'll skip it.
8+
Client caching isn't part of our performance measurement, so we'll skip it.
99
-->
1010
<BlazorCacheBootResources>false</BlazorCacheBootResources>
1111
</PropertyGroup>

src/Components/benchmarkapps/Wasm.Performance/dockerfile

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -25,22 +25,12 @@ RUN git init \
2525

2626
RUN ./restore.sh
2727
RUN npm run build
28-
RUN .dotnet/dotnet publish -c Release --no-restore -o /app ./src/Components/benchmarkapps/Wasm.Performance/Driver/Wasm.Performance.Driver.csproj
28+
RUN .dotnet/dotnet publish -c Release -r linux-x64 --sc true -o /app ./src/Components/benchmarkapps/Wasm.Performance/Driver/Wasm.Performance.Driver.csproj
2929
RUN chmod +x /app/Wasm.Performance.Driver
3030

3131
WORKDIR /app
32-
# NOTE: This has been commented out because it is causing our builds to get a build warning
33-
# because we are pulling this container image from docker.io. We should consider whether
34-
# we need this code in our repo at all, and if not remove it.
35-
# If we do need it then we need to get the container image imported into mcr.microsoft.com
36-
#
37-
# I have opened up a PR to do this, however it is not certain we'll be allowed to do this
38-
# and there is further legal/compliance work that needs to be done. In the meantime commenting
39-
# this out should get our builds to green again whilst this issue is resolved.
40-
#
41-
# PR: https://github.com/microsoft/mcr/pull/3232
42-
#
43-
# FROM selenium/standalone-chrome:124.0 as final
32+
33+
FROM mcr.microsoft.com/playwright/dotnet:v1.45.1-jammy-amd64 AS final
4434
COPY --from=build ./app ./
4535
COPY ./exec.sh ./
4636

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
11
#!/usr/bin/env bash
22

3-
/opt/bin/start-selenium-standalone.sh&
43
./Wasm.Performance.Driver $StressRunDuration
5-

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

Lines changed: 0 additions & 20 deletions
This file was deleted.

0 commit comments

Comments
 (0)