[CmdletBinding()]
param([string]$BaselineRef='d0b94d0')
$ErrorActionPreference='Stop'
$taskRoot=[IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../../..'))
$output=Join-Path $taskRoot ('build/BrowserLoadSpeed/HostComparison-'+[DateTimeOffset]::UtcNow.ToUnixTimeMilliseconds())
[void][IO.Directory]::CreateDirectory($output)
$archive=Join-Path $output 'Baseline.zip'
$baseline=Join-Path $output 'Baseline'
Push-Location $taskRoot
try {
$commit=(& git rev-parse ($BaselineRef+'^{commit}')).Trim()
if($LASTEXITCODE -ne 0){throw 'The baseline must resolve to a Git commit.'}
& git archive --format=zip ('--output='+$archive) $commit
if($LASTEXITCODE -ne 0){throw 'Could not export the frozen baseline sources.'}
Expand-Archive -LiteralPath $archive -DestinationPath $baseline
$project=Join-Path $output 'BaselineProbe.csproj'
$reference=[Security.SecurityElement]::Escape((Join-Path $baseline 'Source/XFESystem.Browser/XFESystem.Browser.csproj'))
$profile=[Security.SecurityElement]::Escape((Join-Path $PSScriptRoot 'LoadingProfile.cs'))
$canvas=[Security.SecurityElement]::Escape((Join-Path $PSScriptRoot '../ProductionProbe/WindowsTextCanvas.cs'))
@"
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup><OutputType>Exe</OutputType><TargetFramework>net10.0-windows</TargetFramework><UseWindowsForms>true</UseWindowsForms><ImplicitUsings>enable</ImplicitUsings><Nullable>enable</Nullable><EnableDefaultCompileItems>false</EnableDefaultCompileItems></PropertyGroup>
<ItemGroup><ProjectReference Include="$reference"/><Compile Include="$profile"/><Compile Include="$canvas"/><Compile Include="Main.cs"/></ItemGroup>
</Project>
"@ | Set-Content -LiteralPath $project -Encoding UTF8
'LoadingProfile.Run(Path.GetFullPath(args[0]), args[1]);' | Set-Content -LiteralPath (Join-Path $output 'Main.cs') -Encoding UTF8
& dotnet run --project $project -c Release --artifacts-path (Join-Path $output 'BeforeArtifacts') -- $baseline Before *> (Join-Path $output 'Before.log')
if($LASTEXITCODE -ne 0){throw ('Baseline loading profile failed: '+$output)}
& dotnet run --project (Join-Path $PSScriptRoot 'PreviewProfile.csproj') -c Release --artifacts-path (Join-Path $output 'AfterArtifacts') -- $taskRoot After --loading *> (Join-Path $output 'After.log')
if($LASTEXITCODE -ne 0){throw ('Current loading profile failed: '+$output)}
$beforePath=Get-Content -LiteralPath (Join-Path $output 'Before.log') -Encoding UTF8 | Select-Object -Last 1
$afterPath=Get-Content -LiteralPath (Join-Path $output 'After.log') -Encoding UTF8 | Select-Object -Last 1
$before=Get-Content -LiteralPath $beforePath -Raw -Encoding UTF8 | ConvertFrom-Json
$after=Get-Content -LiteralPath $afterPath -Raw -Encoding UTF8 | ConvertFrom-Json
if(!$before.Passed -or !$after.Passed){throw 'A loading profile did not pass.'}
$rows=@()
foreach($kind in @('IndexedCss','PlainMarkdown','WebsiteParity','Monaco')) {
$old=@($before.Cases | Where-Object {$_.Kind -ceq $kind})
$new=@($after.Cases | Where-Object {$_.Kind -ceq $kind})
if($old.Count -ne 3 -or $new.Count -ne 3){throw ('Missing repeated cases: '+$kind)}
for($i=0;$i -lt 3;$i++) {
if($old[$i].RenderSha256 -cne $new[$i].RenderSha256){throw ('Layout, color or paint commands changed: '+$kind)}
}
$oldTime=@($old.ReadyMilliseconds | Sort-Object)[1];$newTime=@($new.ReadyMilliseconds | Sort-Object)[1]
$rows+=[ordered]@{Case=$kind;BeforeMedianMilliseconds=$oldTime;AfterMedianMilliseconds=$newTime;Speedup=$oldTime/$newTime;
BeforeSelectorEvaluations=$old[0].CssSelectorEvaluations;AfterSelectorEvaluations=$new[0].CssSelectorEvaluations;RenderSignaturesEqual=$true}
}
[ordered]@{Kind='ProductionBrowserLoadingHostComparison';Passed=$true;HostOnly=$true;NativeAcceptance=$false;
BaselineCommit=$commit;Before=$beforePath;After=$afterPath;Rows=$rows} | ConvertTo-Json -Depth 5 |
Set-Content -LiteralPath (Join-Path $output 'Comparison.json') -Encoding UTF8
Write-Output ('Host loading comparison: '+(Join-Path $output 'Comparison.json'))
} finally {Pop-Location}
[CmdletBinding()]
param([string]$BaselineRef='d0b94d0')
$ErrorActionPreference='Stop'
$taskRoot=[IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../../..'))
$output=Join-Path $taskRoot ('build/BrowserLoadSpeed/HostComparison-'+[DateTimeOffset]::UtcNow.ToUnixTimeMilliseconds())
[void][IO.Directory]::CreateDirectory($output)
$archive=Join-Path $output 'Baseline.zip'
$baseline=Join-Path $output 'Baseline'
Push-Location $taskRoot
try {
$commit=(& git rev-parse ($BaselineRef+'^{commit}')).Trim()
if($LASTEXITCODE -ne 0){throw 'The baseline must resolve to a Git commit.'}
& git archive --format=zip ('--output='+$archive) $commit
if($LASTEXITCODE -ne 0){throw 'Could not export the frozen baseline sources.'}
Expand-Archive -LiteralPath $archive -DestinationPath $baseline
$project=Join-Path $output 'BaselineProbe.csproj'
$reference=[Security.SecurityElement]::Escape((Join-Path $baseline 'Source/XFESystem.Browser/XFESystem.Browser.csproj'))
$profile=[Security.SecurityElement]::Escape((Join-Path $PSScriptRoot 'LoadingProfile.cs'))
$canvas=[Security.SecurityElement]::Escape((Join-Path $PSScriptRoot '../ProductionProbe/WindowsTextCanvas.cs'))
@"
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup><OutputType>Exe</OutputType><TargetFramework>net10.0-windows</TargetFramework><UseWindowsForms>true</UseWindowsForms><ImplicitUsings>enable</ImplicitUsings><Nullable>enable</Nullable><EnableDefaultCompileItems>false</EnableDefaultCompileItems></PropertyGroup>
<ItemGroup><ProjectReference Include="$reference"/><Compile Include="$profile"/><Compile Include="$canvas"/><Compile Include="Main.cs"/></ItemGroup>
</Project>
"@ | Set-Content -LiteralPath $project -Encoding UTF8
'LoadingProfile.Run(Path.GetFullPath(args[0]), args[1]);' | Set-Content -LiteralPath (Join-Path $output 'Main.cs') -Encoding UTF8
& dotnet run --project $project -c Release --artifacts-path (Join-Path $output 'BeforeArtifacts') -- $baseline Before *> (Join-Path $output 'Before.log')
if($LASTEXITCODE -ne 0){throw ('Baseline loading profile failed: '+$output)}
& dotnet run --project (Join-Path $PSScriptRoot 'PreviewProfile.csproj') -c Release --artifacts-path (Join-Path $output 'AfterArtifacts') -- $taskRoot After --loading *> (Join-Path $output 'After.log')
if($LASTEXITCODE -ne 0){throw ('Current loading profile failed: '+$output)}
$beforePath=Get-Content -LiteralPath (Join-Path $output 'Before.log') -Encoding UTF8 | Select-Object -Last 1
$afterPath=Get-Content -LiteralPath (Join-Path $output 'After.log') -Encoding UTF8 | Select-Object -Last 1
$before=Get-Content -LiteralPath $beforePath -Raw -Encoding UTF8 | ConvertFrom-Json
$after=Get-Content -LiteralPath $afterPath -Raw -Encoding UTF8 | ConvertFrom-Json
if(!$before.Passed -or !$after.Passed){throw 'A loading profile did not pass.'}
$rows=@()
foreach($kind in @('IndexedCss','PlainMarkdown','WebsiteParity','Monaco')) {
$old=@($before.Cases | Where-Object {$_.Kind -ceq $kind})
$new=@($after.Cases | Where-Object {$_.Kind -ceq $kind})
if($old.Count -ne 3 -or $new.Count -ne 3){throw ('Missing repeated cases: '+$kind)}
for($i=0;$i -lt 3;$i++) {
if($old[$i].RenderSha256 -cne $new[$i].RenderSha256){throw ('Layout, color or paint commands changed: '+$kind)}
}
$oldTime=@($old.ReadyMilliseconds | Sort-Object)[1];$newTime=@($new.ReadyMilliseconds | Sort-Object)[1]
$rows+=[ordered]@{Case=$kind;BeforeMedianMilliseconds=$oldTime;AfterMedianMilliseconds=$newTime;Speedup=$oldTime/$newTime;
BeforeSelectorEvaluations=$old[0].CssSelectorEvaluations;AfterSelectorEvaluations=$new[0].CssSelectorEvaluations;RenderSignaturesEqual=$true}
}
[ordered]@{Kind='ProductionBrowserLoadingHostComparison';Passed=$true;HostOnly=$true;NativeAcceptance=$false;
BaselineCommit=$commit;Before=$beforePath;After=$afterPath;Rows=$rows} | ConvertTo-Json -Depth 5 |
Set-Content -LiteralPath (Join-Path $output 'Comparison.json') -Encoding UTF8
Write-Output ('Host loading comparison: '+(Join-Path $output 'Comparison.json'))
} finally {Pop-Location}