Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[browser] Enable threads in Wasm SDK #85109

Merged
merged 4 commits into from
Apr 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,8 @@ Copyright (c) .NET Foundation. All rights reserved.
<_WasmInvariantGlobalization Condition="'$(_WasmInvariantGlobalization)' == ''">true</_WasmInvariantGlobalization>
<_WasmCopyOutputSymbolsToOutputDirectory>$(CopyOutputSymbolsToOutputDirectory)</_WasmCopyOutputSymbolsToOutputDirectory>
<_WasmCopyOutputSymbolsToOutputDirectory Condition="'$(_WasmCopyOutputSymbolsToOutputDirectory)'==''">true</_WasmCopyOutputSymbolsToOutputDirectory>
<_WasmEnableThreads>$(WasmEnableThreads)</_WasmEnableThreads>
<_WasmEnableThreads Condition="'$(_WasmEnableThreads)' == ''">false</_WasmEnableThreads>
<_WasmEnableWebcil>$(WasmEnableWebcil)</_WasmEnableWebcil>
<_WasmEnableWebcil Condition="'$(_WasmEnableWebcil)' == ''">false</_WasmEnableWebcil>
<_BlazorWebAssemblyStartupMemoryCache>$(BlazorWebAssemblyStartupMemoryCache)</_BlazorWebAssemblyStartupMemoryCache>
Expand Down Expand Up @@ -203,6 +205,7 @@ Copyright (c) .NET Foundation. All rights reserved.
CopySymbols="$(_WasmCopyOutputSymbolsToOutputDirectory)"
OutputPath="$(OutputPath)"
FingerprintDotNetJs="$(WasmFingerprintDotnetJs)"
EnableThreads="$(_WasmEnableThreads)"
>
<Output TaskParameter="AssetCandidates" ItemName="_BuildAssetsCandidates" />
<Output TaskParameter="FilesToRemove" ItemName="_WasmBuildFilesToRemove" />
Expand Down Expand Up @@ -374,6 +377,7 @@ Copyright (c) .NET Foundation. All rights reserved.
ExistingAssets="@(_WasmPublishPrefilteredAssets)"
DotNetJsVersion="$(_DotNetJsVersion)"
FingerprintDotNetJs="$(WasmFingerprintDotnetJs)"
EnableThreads="$(_WasmEnableThreads)"
IsWebCilEnabled="$(_WasmEnableWebcil)"
>
<Output TaskParameter="NewCandidates" ItemName="_NewWasmPublishStaticWebAssets" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,26 @@ namespace Microsoft.NET.Sdk.WebAssembly;

public class AssetsComputingHelper
{
private static readonly string[] monoPackageIds = new[]
{
"Microsoft.NETCore.App.Runtime.Mono.browser-wasm",
"Microsoft.NETCore.App.Runtime.Mono.multithread.browser-wasm",
"Microsoft.NETCore.App.Runtime.Mono.perftrace.browser-wasm",
};

public static bool ShouldFilterCandidate(
ITaskItem candidate,
bool timezoneSupport,
bool invariantGlobalization,
bool copySymbols,
string customIcuCandidateFilename,
bool enableThreads,
out string reason)
{
var extension = candidate.GetMetadata("Extension");
var fileName = candidate.GetMetadata("FileName");
var assetType = candidate.GetMetadata("AssetType");
var fromMonoPackage = string.Equals(
candidate.GetMetadata("NuGetPackageId"),
"Microsoft.NETCore.App.Runtime.Mono.browser-wasm",
StringComparison.Ordinal);
bool fromMonoPackage = IsFromMonoPackage(candidate);

reason = extension switch
{
Expand All @@ -45,7 +50,7 @@ public static bool ShouldFilterCandidate(
".json" when fromMonoPackage && (fileName == "emcc-props" || fileName == "package") => $"{fileName}{extension} is not used by Blazor",
".ts" when fromMonoPackage && fileName == "dotnet.d" => "dotnet type definition is not used by Blazor",
".ts" when fromMonoPackage && fileName == "dotnet-legacy.d" => "dotnet type definition is not used by Blazor",
".js" when assetType == "native" && fileName != "dotnet" => $"{fileName}{extension} is not used by Blazor",
".js" when assetType == "native" && !(fileName == "dotnet" || enableThreads && fileName == "dotnet.worker") => $"{fileName}{extension} is not used by Blazor",
".pdb" when !copySymbols => "copying symbols is disabled",
".symbols" when fromMonoPackage => "extension .symbols is not required.",
_ => null
Expand All @@ -54,6 +59,12 @@ public static bool ShouldFilterCandidate(
return reason != null;
}

private static bool IsFromMonoPackage(ITaskItem candidate)
{
string packageId = candidate.GetMetadata("NuGetPackageId");
return monoPackageIds.Contains(packageId, StringComparer.Ordinal);
}

public static string GetCandidateRelativePath(ITaskItem candidate)
{
var destinationSubPath = candidate.GetMetadata("DestinationSubPath");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ public class ComputeWasmBuildAssets : Task

public bool FingerprintDotNetJs { get; set; }

public bool EnableThreads { get; set; }

[Output]
public ITaskItem[] AssetCandidates { get; set; }

Expand Down Expand Up @@ -79,7 +81,7 @@ public override bool Execute()
for (int i = 0; i < Candidates.Length; i++)
{
var candidate = Candidates[i];
if (AssetsComputingHelper.ShouldFilterCandidate(candidate, TimeZoneSupport, InvariantGlobalization, CopySymbols, customIcuCandidateFilename, out var reason))
if (AssetsComputingHelper.ShouldFilterCandidate(candidate, TimeZoneSupport, InvariantGlobalization, CopySymbols, customIcuCandidateFilename, EnableThreads, out var reason))
{
Log.LogMessage(MessageImportance.Low, "Skipping asset '{0}' because '{1}'", candidate.ItemSpec, reason);
filesToRemove.Add(candidate);
Expand All @@ -104,14 +106,15 @@ public override bool Execute()
continue;
}

if (candidate.GetMetadata("FileName") == "dotnet" && candidate.GetMetadata("Extension") == ".js")
string candidateFileName = candidate.GetMetadata("FileName");
if ((candidateFileName == "dotnet" || candidateFileName == "dotnet.worker") && candidate.GetMetadata("Extension") == ".js")
{
string newDotnetJSFileName = null;
string newDotNetJSFullPath = null;
if (FingerprintDotNetJs)
{
var itemHash = FileHasher.GetFileHash(candidate.ItemSpec);
newDotnetJSFileName = $"dotnet.{candidate.GetMetadata("NuGetPackageVersion")}.{itemHash}.js";
newDotnetJSFileName = $"{candidateFileName}.{candidate.GetMetadata("NuGetPackageVersion")}.{itemHash}.js";

var originalFileFullPath = Path.GetFullPath(candidate.ItemSpec);
var originalFileDirectory = Path.GetDirectoryName(originalFileFullPath);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ public class ComputeWasmPublishAssets : Task

public bool FingerprintDotNetJs { get; set; }

public bool EnableThreads { get; set; }

public bool IsWebCilEnabled { get; set; }

[Output]
Expand Down Expand Up @@ -163,8 +165,10 @@ private List<ITaskItem> ProcessNativeAssets(
var key = kvp.Key;
var asset = kvp.Value;
var isDotNetJs = IsDotNetJs(key);
var isDotNetWorkerJs = IsDotNetWorkerJs(key);
var isDotNetWasm = IsDotNetWasm(key);
if (!isDotNetJs && !isDotNetWasm)

if (!isDotNetJs && !isDotNetWasm && !isDotNetWorkerJs)
{
if (resolvedNativeAssetToPublish.TryGetValue(Path.GetFileName(asset.GetMetadata("OriginalItemSpec")), out var existing))
{
Expand Down Expand Up @@ -197,11 +201,16 @@ private List<ITaskItem> ProcessNativeAssets(
{
var aotDotNetJs = WasmAotAssets.SingleOrDefault(a => $"{a.GetMetadata("FileName")}{a.GetMetadata("Extension")}" == "dotnet.js");
ITaskItem newDotNetJs = null;
if (aotDotNetJs != null && FingerprintDotNetJs)
if (aotDotNetJs != null)
{
newDotNetJs = new TaskItem(Path.GetFullPath(aotDotNetJs.ItemSpec), asset.CloneCustomMetadata());
newDotNetJs.SetMetadata("OriginalItemSpec", aotDotNetJs.ItemSpec);
newDotNetJs.SetMetadata("RelativePath", $"_framework/{$"dotnet.{DotNetJsVersion}.{FileHasher.GetFileHash(aotDotNetJs.ItemSpec)}.js"}");

string relativePath = FingerprintDotNetJs
? $"_framework/{$"dotnet.{DotNetJsVersion}.{FileHasher.GetFileHash(aotDotNetJs.ItemSpec)}.js"}"
: "_framework/dotnet.js";

newDotNetJs.SetMetadata("RelativePath", relativePath);

updateMap.Add(asset.ItemSpec, newDotNetJs);
Log.LogMessage(MessageImportance.Low, "Replacing asset '{0}' with AoT version '{1}'", asset.ItemSpec, newDotNetJs.ItemSpec);
Expand All @@ -221,6 +230,35 @@ private List<ITaskItem> ProcessNativeAssets(
continue;
}

if (isDotNetWorkerJs)
{
var aotDotNetWorkerJs = WasmAotAssets.SingleOrDefault(a => $"{a.GetMetadata("FileName")}{a.GetMetadata("Extension")}" == "dotnet.worker.js");
ITaskItem newDotNetWorkerJs = null;
if (aotDotNetWorkerJs != null)
{
newDotNetWorkerJs = new TaskItem(Path.GetFullPath(aotDotNetWorkerJs.ItemSpec), asset.CloneCustomMetadata());
newDotNetWorkerJs.SetMetadata("OriginalItemSpec", aotDotNetWorkerJs.ItemSpec);
newDotNetWorkerJs.SetMetadata("RelativePath", "_framework/dotnet.worker.js");

updateMap.Add(asset.ItemSpec, newDotNetWorkerJs);
Log.LogMessage(MessageImportance.High, "Replacing asset '{0}' with AoT version '{1}'", asset.ItemSpec, newDotNetWorkerJs.ItemSpec);
}
else
{
newDotNetWorkerJs = new TaskItem(asset);
newDotNetWorkerJs.SetMetadata("RelativePath", "_framework/dotnet.worker.js");
Log.LogMessage(MessageImportance.High, "Promoting asset '{0}' to Publish asset.", asset.ItemSpec);
}

ApplyPublishProperties(newDotNetWorkerJs);
nativeStaticWebAssets.Add(newDotNetWorkerJs);
if (resolvedNativeAssetToPublish.TryGetValue("dotnet.worker.js", out var resolved))
{
filesToRemove.Add(resolved);
}
continue;
}

if (isDotNetWasm)
{
var aotDotNetWasm = WasmAotAssets.SingleOrDefault(a => $"{a.GetMetadata("FileName")}{a.GetMetadata("Extension")}" == "dotnet.wasm");
Expand Down Expand Up @@ -262,6 +300,8 @@ static bool IsDotNetJs(string key)
return fileName.StartsWith("dotnet.", StringComparison.Ordinal) && fileName.EndsWith(".js", StringComparison.Ordinal) && !fileName.Contains("worker");
}

static bool IsDotNetWorkerJs(string key) => string.Equals("dotnet.worker.js", Path.GetFileName(key), StringComparison.Ordinal);

static bool IsDotNetWasm(string key) => string.Equals("dotnet.wasm", Path.GetFileName(key), StringComparison.Ordinal);
}

Expand Down Expand Up @@ -540,7 +580,7 @@ private void GroupResolvedFilesToPublish(

foreach (var candidate in resolvedFilesToPublish)
{
if (AssetsComputingHelper.ShouldFilterCandidate(candidate, TimeZoneSupport, InvariantGlobalization, CopySymbols, customIcuCandidateFilename, out var reason))
if (AssetsComputingHelper.ShouldFilterCandidate(candidate, TimeZoneSupport, InvariantGlobalization, CopySymbols, customIcuCandidateFilename, EnableThreads, out var reason))
{
Log.LogMessage(MessageImportance.Low, "Skipping asset '{0}' because '{1}'", candidate.ItemSpec, reason);
if (!resolvedFilesToPublishToRemove.ContainsKey(candidate.ItemSpec))
Expand Down