[wasm-ep] Minimal diagnostic tracing configuration and sample (#69158)
authorAleksey Kliger (λgeek) <aleksey@lambdageek.org>
Thu, 19 May 2022 00:27:44 +0000 (20:27 -0400)
committerGitHub <noreply@github.com>
Thu, 19 May 2022 00:27:44 +0000 (20:27 -0400)
commitb15ff0617e0edc65be9f50d760d827469429c3ba
tree7e3efcd68e4d5c42467e2a391b2364d3a0d7cdca
parent42d1644a1635c334cabe6b216f91e98cd7606248
[wasm-ep] Minimal diagnostic tracing configuration and sample (#69158)

* Adds a `/p:WasmEnablePerfTracing=true` configuration.

   In this configuration the runtime is built with threading (`MonoWasmThreads` property is true), but user C# code is not allowed to start threads and doesn't use the portable threadpool (`MonoWasmThreadsNoUser` property is also true).

   The upshot is that EventPipe can start threads but user code is still single-threaded.

* Adds a `MONO.diagnostics` interface in JavaScript.  There's a single method for now `createEventPipeSession` which creates a session that can save a trace to a file on the virtual file system.  JS code (or a user in a dev console) needs to call `start()` and `stop()` on the session object to begin collecting samples.    The data is saved temporarily to the Emscripten VFS and can be retrived into a JavaScript Blob (and from there downloaded to a file outside the browser).

* Adds a sample that runs an async task for five seconds and collects samples and then triggers a `click()` to download the trace file out of the browser.

* Adds a TS module to help with working with uint64_t values in the emscripten heap.

* Exposes empscripten Module.stackSave, stackRestore and stackAlloc operations to the runtime TS modules.  Use for working with event pipe session ID outparam.

---

* add DISABLE_WASM_USER_THREADS mono cmake option

* Disable Thread.StartInternal icall if DISABLE_WASM_USER_THREADS

   if threading is enabled for the runtime internally, but disabled for user code, throw PNSE

* add an eventpipe sample

* [wasm-ep] (browser-eventpipe sample) run loop for longer

* [samples/wasm-eventpipe] make an async task sample

   change the sample to do some work asynchronously using setTimeout instead of blocking

* [wasm] Add MONO.diagnostics interface

   Binds enable, start, disable methods defaulting to non-streaming FILE mode

* if wasm threads are disabled, but perftracing is enabled, don't log overlapped io events

* fix whitespace and nits

* don't need try/finally in the sample anymore

* more whitespace

* add start method to EventPipeSession interface

* don't run wasm-eventpipe sample on CI lanes without perftracing

* more whitespace

* fix eslint warnings, default rundown to true, allow callback for traceFilePath option

* add EventPipeSession.getTraceBlob

   for retrieving the collected traces instead of exposing the emscripten VFS directly.

   update the sample to use URL.createObjectURL (session.getTraceBlob()) to create the download link

* [browser-eventpipe sample] remove unnecessary ref assemblies

* use ep_char8_t for C decls of event pipe wasm exports

* Use stack allocation for temporaries

   Expose the emscripten stack allocation API

* Use 32-bit EventPipe session ID on WASM

   64 bit integers are awkward to work with in JavaScript.

   The EventPipe session ID is derived from a pointer address, so even though it is nominally a 64-bit value, in practice the top bits are zero.

   Use a 32-bit int to represent the session ID on the javascript side and convert to 64-bit in C when calling down to the EventPipe APIs

* Make the sample do more work in managed

   give the sample profiler some non-empty samples to collect

* Move withStackAlloc to memory.ts

* simplify VFS .nettrace file naming

   Just use consecutive integers to uniquify the session traces.  Dont' need a fancy timestamp in the VFS (which would also not be unique if you create sessions below the timestamp resolution)

* Add overloads to memory.withStackAlloc to avoid creating closures

   Pass additional arguments to the callback function

* sample: explain why there's a 10s pause

* move createEventPipeSession callback to a function

   ensures the closure is created once

* Use a tuple type for withStackAlloc

* use unsigned 32-bit get/set in cuint64 get/set

* fix whitespace
23 files changed:
src/libraries/tests.proj
src/mono/System.Private.CoreLib/src/System/Threading/Overlapped.cs
src/mono/cmake/config.h.in
src/mono/cmake/options.cmake
src/mono/mono/component/CMakeLists.txt
src/mono/mono/component/event_pipe-stub.c
src/mono/mono/component/event_pipe-wasm.h [new file with mode: 0644]
src/mono/mono/component/event_pipe.c
src/mono/mono/metadata/threads.c
src/mono/sample/wasm/browser-eventpipe/Makefile [new file with mode: 0644]
src/mono/sample/wasm/browser-eventpipe/Program.cs [new file with mode: 0644]
src/mono/sample/wasm/browser-eventpipe/Wasm.Browser.EventPipe.Sample.csproj [new file with mode: 0644]
src/mono/sample/wasm/browser-eventpipe/index.html [new file with mode: 0644]
src/mono/sample/wasm/browser-eventpipe/main.js [new file with mode: 0644]
src/mono/wasm/runtime/buffers.ts
src/mono/wasm/runtime/cuint64.ts [new file with mode: 0644]
src/mono/wasm/runtime/cwraps.ts
src/mono/wasm/runtime/diagnostics.ts [new file with mode: 0644]
src/mono/wasm/runtime/dotnet.d.ts
src/mono/wasm/runtime/exports.ts
src/mono/wasm/runtime/memory.ts
src/mono/wasm/runtime/types.ts
src/mono/wasm/runtime/types/emscripten.ts