Skip to content

Commit

Permalink
[browser][MT] enable finalizer thread, run most tests in threadpool (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
pavelsavara authored Dec 12, 2023
1 parent 69bbdb8 commit cea45aa
Show file tree
Hide file tree
Showing 11 changed files with 38 additions and 19 deletions.
2 changes: 2 additions & 0 deletions eng/testing/tests.browser.targets
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,8 @@
<_AppArgs Condition="'$(IsFunctionalTest)' != 'true' and '$(WasmMainAssemblyFileName)' != ''">--run $(WasmMainAssemblyFileName)</_AppArgs>
<_AppArgs Condition="'$(IsFunctionalTest)' == 'true'">--run $(AssemblyName).dll</_AppArgs>

<_XUnitBackgroundExec Condition="'$(_XUnitBackgroundExec)' == '' and '$(MonoWasmBuildVariant)' == 'multithread'">true</_XUnitBackgroundExec>
<WasmTestAppArgs Condition="'$(_XUnitBackgroundExec)' == 'true'">$(WasmTestAppArgs) -backgroundExec</WasmTestAppArgs>
<_AppArgs Condition="'$(WasmTestAppArgs)' != ''">$(_AppArgs) $(WasmTestAppArgs)</_AppArgs>

<WasmXHarnessMonoArgs Condition="'$(XunitShowProgress)' == 'true'">$(WasmXHarnessMonoArgs) --setenv=XHARNESS_LOG_TEST_START=1</WasmXHarnessMonoArgs>
Expand Down
9 changes: 8 additions & 1 deletion src/libraries/Common/tests/WasmTestRunner/WasmTestRunner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ public static async Task<int> Main(string[] args)
var includedNamespaces = new List<string>();
var includedClasses = new List<string>();
var includedMethods = new List<string>();
var backgroundExec = false;

for (int i = 1; i < args.Length; i++)
{
Expand All @@ -49,6 +50,9 @@ public static async Task<int> Main(string[] args)
includedMethods.Add (args[i + 1]);
i++;
break;
case "-backgroundExec":
backgroundExec = true;
break;
default:
throw new ArgumentException($"Invalid argument '{option}'.");
}
Expand All @@ -68,7 +72,10 @@ public static async Task<int> Main(string[] args)
{
await Task.Yield();
}

if (backgroundExec)
{
return await Task.Run(() => runner.Run());
}
return await runner.Run();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
<WasmEnableLegacyJsInterop Condition="'$(WasmEnableLegacyJsInterop)' == ''">true</WasmEnableLegacyJsInterop>
<DefineConstants Condition="'$(WasmEnableLegacyJsInterop)' == 'false'">$(DefineConstants);DISABLE_LEGACY_JS_INTEROP</DefineConstants>
<Scenario>WasmTestOnBrowser</Scenario>
<!-- this unit test depends on JavaScript interop and doesn't need heavy threading. So we can run it in UI thread. TODO: Drop this when we have automatic JSInterop dispatch to UI thread. -->
<_XUnitBackgroundExec>false</_XUnitBackgroundExec>
</PropertyGroup>

<ItemGroup Condition="'$(WasmEnableLegacyJsInterop)' != 'false'">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
<DefineConstants Condition="'$(WasmEnableLegacyJsInterop)' == 'false'">$(DefineConstants);DISABLE_LEGACY_JS_INTEROP</DefineConstants>
<!-- Use following lines to write the generated files to disk. -->
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
<!-- this unit test depends on JavaScript interop and doesn't need heavy threading. So we can run it in UI thread. TODO: Drop this when we have automatic JSInterop dispatch to UI thread. -->
<_XUnitBackgroundExec>false</_XUnitBackgroundExec>
</PropertyGroup>
<ItemGroup>
<Compile Include="System\Runtime\InteropServices\JavaScript\JavaScriptTestHelper.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1004,6 +1004,9 @@ public static async Task InitializeAsync()
await Setup();
// Log("JavaScriptTestHelper.mjs imported");
}

// this gives browser chance to serve UI thread event loop before every test
await Task.Yield();
}

public static Task DisposeAsync()
Expand Down
4 changes: 4 additions & 0 deletions src/libraries/tests.proj
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,9 @@
<ProjectExclusions Include="$(MSBuildThisFileDirectory)System.Net.Http\tests\FunctionalTests\System.Net.Http.Functional.Tests.csproj" />
<!-- Issue: https://github.com/dotnet/runtime/issues/74413 -->
<ProjectExclusions Include="$(MSBuildThisFileDirectory)System.Net.WebSockets.Client\tests\System.Net.WebSockets.Client.Tests.csproj" />
<!-- Issue: https://github.com/dotnet/runtime/issues/95795 -->
<ProjectExclusions Include="$(MSBuildThisFileDirectory)System.Runtime\tests\System.Globalization.Tests\Hybrid\System.Globalization.Hybrid.WASM.Tests.csproj" />
<ProjectExclusions Include="$(MSBuildThisFileDirectory)System.Runtime\tests\System.Globalization.Calendars.Tests\Hybrid\System.Globalization.Calendars.Hybrid.WASM.Tests.csproj" />
</ItemGroup>

<!-- Aggressive Trimming related failures -->
Expand Down Expand Up @@ -592,6 +595,7 @@
<SmokeTestProject Include="$(MonoProjectRoot)sample\wasm\browser-threads-minimal\Wasm.Browser.Threads.Minimal.Sample.csproj" />
-->
<SmokeTestProject Include="$(MSBuildThisFileDirectory)System.Net.WebSockets.Client\tests\System.Net.WebSockets.Client.Tests.csproj" />
<SmokeTestProject Include="$(MSBuildThisFileDirectory)System.Runtime.InteropServices.JavaScript\tests\System.Runtime.InteropServices.JavaScript.UnitTests\System.Runtime.InteropServices.JavaScript.Tests.csproj" />
<!-- ActiveIssue https://github.com/dotnet/runtime/issues/88084
<SmokeTestProject Include="$(MSBuildThisFileDirectory)System.Net.Http\tests\FunctionalTests\System.Net.Http.Functional.Tests.csproj" />
-->
Expand Down
2 changes: 2 additions & 0 deletions src/mono/wasm/runtime/cwraps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ const threading_cwraps: SigLine[] = MonoWasmThreads ? [
[true, "mono_wasm_diagnostic_server_thread_attach_to_runtime", "void", []],
[true, "mono_wasm_diagnostic_server_post_resume_runtime", "void", []],
[true, "mono_wasm_diagnostic_server_create_stream", "number", []],
[false, "mono_wasm_init_finalizer_thread", null, []],
] : [];

// when the method is assigned/cached at usage, instead of being invoked directly from cwraps, it can't be marked lazy, because it would be re-bound on each call
Expand Down Expand Up @@ -181,6 +182,7 @@ export interface t_ThreadingCwraps {
mono_wasm_diagnostic_server_thread_attach_to_runtime(): void;
mono_wasm_diagnostic_server_post_resume_runtime(): void;
mono_wasm_diagnostic_server_create_stream(): VoidPtr;
mono_wasm_init_finalizer_thread(): void;
}

export interface t_ProfilerCwraps {
Expand Down
11 changes: 3 additions & 8 deletions src/mono/wasm/runtime/driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ char *mono_method_get_full_name (MonoMethod *method);
extern void mono_register_timezones_bundle (void);
#endif /* INVARIANT_TIMEZONE */
extern void mono_wasm_set_entrypoint_breakpoint (const char* assembly_name, int method_token);
static void mono_wasm_init_finalizer_thread (void);

extern void mono_bundled_resources_add_assembly_resource (const char *id, const char *name, const uint8_t *data, uint32_t size, void (*free_func)(void *, void*), void *free_data);
extern void mono_bundled_resources_add_assembly_symbol_resource (const char *id, const uint8_t *data, uint32_t size, void (*free_func)(void *, void *), void *free_data);
Expand Down Expand Up @@ -542,9 +541,6 @@ mono_wasm_load_runtime (const char *unused, int debug_level)

mono_thread_set_main (mono_thread_current ());

// TODO: we can probably delay starting the finalizer thread even longer - maybe from JS
// once we're done with loading and are about to begin running some managed code.
mono_wasm_init_finalizer_thread ();
}

EMSCRIPTEN_KEEPALIVE MonoAssembly*
Expand Down Expand Up @@ -1296,12 +1292,11 @@ mono_wasm_profiler_init_browser (const char *desc)

#endif

static void
EMSCRIPTEN_KEEPALIVE void
mono_wasm_init_finalizer_thread (void)
{
// At this time we don't use a dedicated thread for finalization even if threading is enabled.
// Finalizers periodically run on the main thread
#if 0
// in the single threaded build, finalizers periodically run on the main thread instead.
#ifndef DISABLE_THREADS
mono_gc_init_finalizer_thread ();
#endif
}
Expand Down
4 changes: 1 addition & 3 deletions src/mono/wasm/runtime/exports-binding.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { mono_wasm_asm_loaded } from "./startup";
import { mono_wasm_diagnostic_server_on_server_thread_created } from "./diagnostics/server_pthread";
import { mono_wasm_diagnostic_server_on_runtime_server_init, mono_wasm_event_pipe_early_startup_callback } from "./diagnostics";
import { mono_wasm_diagnostic_server_stream_signal_work_available } from "./diagnostics/server_pthread/stream-queue";
import { mono_log_debug, mono_log_warn, mono_wasm_trace_logger } from "./logging";
import { mono_log_warn, mono_wasm_trace_logger } from "./logging";
import { mono_wasm_profiler_leave, mono_wasm_profiler_enter } from "./profiler";
import { mono_wasm_change_case, mono_wasm_change_case_invariant } from "./hybrid-globalization/change-case";
import { mono_wasm_compare_string, mono_wasm_ends_with, mono_wasm_starts_with, mono_wasm_index_of } from "./hybrid-globalization/collations";
Expand Down Expand Up @@ -163,8 +163,6 @@ export function replace_linker_placeholders(imports: WebAssembly.Imports) {
const stubFn = env[shortName];
if (typeof stubFn !== "function") throw new Error(`Expected ${shortName} to be a function`);
env[shortName] = realFn;
mono_log_debug(`Replaced WASM import ${shortName} stub ${stubFn.name} with ${realFn.name || "minified implementation"}`);
}
}

}
8 changes: 6 additions & 2 deletions src/mono/wasm/runtime/startup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import WasmEnableLegacyJsInterop from "consts:wasmEnableLegacyJsInterop";

import { DotnetModuleInternal, CharPtrNull } from "./types/internal";
import { linkerDisableLegacyJsInterop, ENVIRONMENT_IS_PTHREAD, ENVIRONMENT_IS_NODE, exportedRuntimeAPI, INTERNAL, loaderHelpers, Module, runtimeHelpers, createPromiseController, mono_assert, linkerWasmEnableSIMD, linkerWasmEnableEH, ENVIRONMENT_IS_WORKER } from "./globals";
import cwraps, { init_c_exports } from "./cwraps";
import cwraps, { init_c_exports, threads_c_functions as tcwraps } from "./cwraps";
import { mono_wasm_raise_debug_event, mono_wasm_runtime_ready } from "./debug";
import { toBase64StringImpl } from "./base64";
import { mono_wasm_init_aot_profiler, mono_wasm_init_browser_profiler } from "./profiler";
Expand Down Expand Up @@ -334,6 +334,10 @@ async function postRunAsync(userpostRun: (() => void)[]) {
Module["FS_createPath"]("/", "usr", true, true);
Module["FS_createPath"]("/", "usr/share", true, true);

if (MonoWasmThreads) {
tcwraps.mono_wasm_init_finalizer_thread();
}

// all user Module.postRun callbacks
userpostRun.map(fn => fn());
endMeasure(mark, MeasuredBlock.postRun);
Expand Down Expand Up @@ -561,7 +565,7 @@ async function mono_wasm_before_memory_snapshot() {
endMeasure(mark, MeasuredBlock.memorySnapshot);
}

async function maybeSaveInterpPgoTable () {
async function maybeSaveInterpPgoTable() {
// If the application exited abnormally, don't save the table. It probably doesn't contain useful data,
// and saving would overwrite any existing table from a previous successful run.
// We treat exiting with a code of 0 as equivalent to if the app is still running - it's perfectly fine
Expand Down
10 changes: 5 additions & 5 deletions src/mono/wasm/test-main.js
Original file line number Diff line number Diff line change
Expand Up @@ -350,11 +350,11 @@ async function run() {

if (ENVIRONMENT_IS_WEB && runArgs.memorySnapshot) {
if (globalThis.isSecureContext) {
const dryOk = await dry_run(runArgs);
if (!dryOk) {
mono_exit(1, "Failed during dry run");
return;
}
const dryOk = await dry_run(runArgs);
if (!dryOk) {
mono_exit(1, "Failed during dry run");
return;
}
} else {
console.log("Skipping dry run as the context is not secure and the snapshot would be not trusted.");
}
Expand Down

0 comments on commit cea45aa

Please sign in to comment.