Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
8166db7
add DISABLE_WASM_USER_THREADS mono cmake option
lambdageek Apr 26, 2022
a4dd0a8
Disable Thread.StartInternal icall if DISABLE_WASM_USER_THREADS
lambdageek Apr 29, 2022
3f6af6f
add an eventpipe sample
lambdageek May 2, 2022
cc7162f
[wasm-ep] (browser-eventpipe sample) run loop for longer
lambdageek May 2, 2022
f269cee
[samples/wasm-eventpipe] make an async task sample
lambdageek May 9, 2022
18f73b9
[wasm] Add MONO.diagnostics interface
lambdageek May 9, 2022
75d33cb
if wasm threads are disabled, but perftracing is enabled, don't log
lambdageek May 10, 2022
327502d
fix whitespace and nits
lambdageek May 10, 2022
fafeced
don't need try/finally in the sample anymore
lambdageek May 10, 2022
252d06a
more whitespace
lambdageek May 10, 2022
8b54aab
add start method to EventPipeSession interface
lambdageek May 10, 2022
e2e1b66
don't run wasm-eventpipe sample on CI lanes without perftracing
lambdageek May 11, 2022
ded3aeb
more whitespace
lambdageek May 11, 2022
46c1a7c
fix eslint warnings, default rundown to true, allow callback for trac…
lambdageek May 11, 2022
c29915d
add EventPipeSession.getTraceBlob and EventPipeSession.getTraceDataURI
lambdageek May 11, 2022
8287396
[browser-eventpipe sample] remove unnecessary ref assemblies
lambdageek May 11, 2022
a7bd41b
use toBase64StringImpl instead of btoa
lambdageek May 11, 2022
be8d199
use int64_t for event pipe session IDs
lambdageek May 11, 2022
63190bd
use ep_char8_t for C decls of event pipe wasm exports
lambdageek May 11, 2022
4c50aa6
fix debug output
lambdageek May 11, 2022
a67ecd4
fix endianness issue
lambdageek May 11, 2022
f0577f4
Use stack allocation for temporaries
lambdageek May 11, 2022
99f2ddf
Use 32-bit EventPipe session ID on WASM
lambdageek May 12, 2022
cdf8909
Make the sample do more work in managed
lambdageek May 12, 2022
9c70c5c
Move withStackAlloc to memory.ts
lambdageek May 16, 2022
5af5b80
fix option description
lambdageek May 16, 2022
8fcb319
simplify VFS .nettrace file naming
lambdageek May 16, 2022
a3d681c
Add overloads to memory.withStackAlloc to avoid creating closures
lambdageek May 16, 2022
173081c
sample: explain why there's a 10s pause
lambdageek May 16, 2022
f07daea
move createEventPipeSession callback to a function
lambdageek May 16, 2022
61dbd2f
Merge remote-tracking branch 'origin/main' into wasm-ep
lambdageek May 18, 2022
886df1b
Merge branch 'main' into wasm-ep
lambdageek May 18, 2022
19f9659
fix whitespace
lambdageek May 18, 2022
c16d22c
Use a tuple type for withStackAlloc
lambdageek May 18, 2022
dc1dbad
fix whitespace
lambdageek May 18, 2022
82ba6c4
go back to explicit args for withStackAlloc insead of rest/spread
lambdageek May 18, 2022
aed3660
use unsigned 32-bit get/set in cuint64 get/set
lambdageek May 18, 2022
0a7381d
cosmetic changes to sample
lambdageek May 18, 2022
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
5 changes: 5 additions & 0 deletions src/libraries/tests.proj
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,11 @@
<ProjectExclusions Include="$(MonoProjectRoot)sample\wasm\browser-mt-eventpipe\Wasm.Browser.ThreadsEP.Sample.csproj" />
</ItemGroup>

<!-- Samples that require a perf-tracing wasm runtime -->
<ItemGroup Condition="'$(TargetOS)' == 'Browser' and '$(WasmEnablePerfTracing)' != 'true'" >
<ProjectExclusions Include="$(MonoProjectRoot)sample\wasm\browser-eventpipe\Wasm.Browser.EventPipe.Sample.csproj" />
</ItemGroup>

<!-- Wasm aot on all platforms -->
<ItemGroup Condition="'$(TargetOS)' == 'Browser' and '$(BuildAOTTestsOnHelix)' == 'true' and '$(RunDisabledWasmTests)' != 'true' and '$(RunAOTCompilation)' == 'true'">
<!-- https://github.com/dotnet/runtime/issues/66118 -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,10 @@ internal sealed unsafe class OverlappedData

success = true;
#if FEATURE_PERFTRACING
#if !(TARGET_BROWSER && !FEATURE_WASM_THREADS)
if (NativeRuntimeEventSource.Log.IsEnabled())
NativeRuntimeEventSource.Log.ThreadPoolIOPack(pNativeOverlapped);
#endif
#endif
return _pNativeOverlapped;
}
Expand Down
3 changes: 3 additions & 0 deletions src/mono/cmake/config.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,9 @@
/* Disable Threads */
#cmakedefine DISABLE_THREADS 1

/* Disable user thread creation on WebAssembly */
#cmakedefine DISABLE_WASM_USER_THREADS 1

/* Disable MONO_LOG_DEST */
#cmakedefine DISABLE_LOG_DEST

Expand Down
1 change: 1 addition & 0 deletions src/mono/cmake/options.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ option (ENABLE_OVERRIDABLE_ALLOCATORS "Enable overridable allocator support")
option (ENABLE_SIGALTSTACK "Enable support for using sigaltstack for SIGSEGV and stack overflow handling, this doesn't work on some platforms")
option (USE_MALLOC_FOR_MEMPOOLS "Use malloc for each single mempool allocation, so tools like Valgrind can run better")
option (STATIC_COMPONENTS "Compile mono runtime components as static (not dynamic) libraries")
option (DISABLE_WASM_USER_THREADS "Disable creation of user managed threads on WebAssembly, only allow runtime internal managed and native threads")

set (MONO_GC "sgen" CACHE STRING "Garbage collector implementation (sgen or boehm). Default: sgen")
set (GC_SUSPEND "default" CACHE STRING "GC suspend method (default, preemptive, coop, hybrid)")
Expand Down
1 change: 1 addition & 0 deletions src/mono/mono/component/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ set(${MONO_DIAGNOSTICS_TRACING_COMPONENT_NAME}-sources
${diagnostic_server_sources}
${MONO_COMPONENT_PATH}/event_pipe.c
${MONO_COMPONENT_PATH}/event_pipe.h
${MONO_COMPONENT_PATH}/event_pipe-wasm.h
${MONO_COMPONENT_PATH}/diagnostics_server.c
${MONO_COMPONENT_PATH}/diagnostics_server.h
)
Expand Down
35 changes: 35 additions & 0 deletions src/mono/mono/component/event_pipe-stub.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include <config.h>
#include "mono/component/event_pipe.h"
#include "mono/component/event_pipe-wasm.h"
#include "mono/metadata/components.h"

static EventPipeSessionID _dummy_session_id;
Expand Down Expand Up @@ -495,3 +496,37 @@ mono_component_event_pipe_init (void)
{
return component_event_pipe_stub_init ();
}

#ifdef HOST_WASM

EMSCRIPTEN_KEEPALIVE gboolean
mono_wasm_event_pipe_enable (const ep_char8_t *output_path,
uint32_t circular_buffer_size_in_mb,
const ep_char8_t *providers,
/* EventPipeSessionType session_type = EP_SESSION_TYPE_FILE, */
/* EventPipieSerializationFormat format = EP_SERIALIZATION_FORMAT_NETTRACE_V4, */
/* bool */ gboolean rundown_requested,
/* IpcStream stream = NULL, */
/* EventPipeSessionSycnhronousCallback sync_callback = NULL, */
/* void *callback_additional_data, */
MonoWasmEventPipeSessionID *out_session_id)
{
if (out_session_id)
*out_session_id = 0;
return 0;
}


EMSCRIPTEN_KEEPALIVE gboolean
mono_wasm_event_pipe_session_start_streaming (MonoWasmEventPipeSessionID session_id)
{
g_assert_not_reached ();
}

EMSCRIPTEN_KEEPALIVE gboolean
mono_wasm_event_pipe_session_disable (MonoWasmEventPipeSessionID session_id)
{
g_assert_not_reached ();
}

#endif /* HOST_WASM */
52 changes: 52 additions & 0 deletions src/mono/mono/component/event_pipe-wasm.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
//

#ifndef _MONO_COMPONENT_EVENT_PIPE_WASM_H
#define _MONO_COMPONENT_EVENT_PIPE_WASM_H

#include <stdint.h>
#include <eventpipe/ep-ipc-pal-types-forward.h>
#include <eventpipe/ep-types-forward.h>
#include <glib.h>

#ifdef HOST_WASM

#include <emscripten.h>

G_BEGIN_DECLS

#if SIZEOF_VOID_P == 4
/* EventPipeSessionID is 64 bits, which is awkward to work with in JS.
Fortunately the actual session IDs are derived from pointers which
are 32-bit on wasm32, so the top bits are zero. */
typedef uint32_t MonoWasmEventPipeSessionID;
#else
#error "EventPipeSessionID is 64-bits, update the JS side to work with it"
#endif

EMSCRIPTEN_KEEPALIVE gboolean
mono_wasm_event_pipe_enable (const ep_char8_t *output_path,
uint32_t circular_buffer_size_in_mb,
const ep_char8_t *providers,
/* EventPipeSessionType session_type = EP_SESSION_TYPE_FILE, */
/* EventPipieSerializationFormat format = EP_SERIALIZATION_FORMAT_NETTRACE_V4, */
/* bool */ gboolean rundown_requested,
/* IpcStream stream = NULL, */
/* EventPipeSessionSycnhronousCallback sync_callback = NULL, */
/* void *callback_additional_data, */
MonoWasmEventPipeSessionID *out_session_id);

EMSCRIPTEN_KEEPALIVE gboolean
mono_wasm_event_pipe_session_start_streaming (MonoWasmEventPipeSessionID session_id);

EMSCRIPTEN_KEEPALIVE gboolean
mono_wasm_event_pipe_session_disable (MonoWasmEventPipeSessionID session_id);

G_END_DECLS

#endif /* HOST_WASM */


#endif /* _MONO_COMPONENT_EVENT_PIPE_WASM_H */

73 changes: 73 additions & 0 deletions src/mono/mono/component/event_pipe.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,16 @@

#include <config.h>
#include <mono/component/event_pipe.h>
#include <mono/component/event_pipe-wasm.h>
#include <mono/utils/mono-publib.h>
#include <mono/utils/mono-compiler.h>
#include <mono/utils/mono-threads-api.h>
#include <eventpipe/ep.h>
#include <eventpipe/ep-event.h>
#include <eventpipe/ep-event-instance.h>
#include <eventpipe/ep-session.h>


extern void ep_rt_mono_component_init (void);
static bool _event_pipe_component_inited = false;

Expand Down Expand Up @@ -327,3 +330,73 @@ mono_component_event_pipe_init (void)

return &fn_table;
}


#ifdef HOST_WASM


static MonoWasmEventPipeSessionID
ep_to_wasm_session_id (EventPipeSessionID session_id)
{
g_assert (0 == (uint64_t)session_id >> 32);
return (uint32_t)session_id;
}

static EventPipeSessionID
wasm_to_ep_session_id (MonoWasmEventPipeSessionID session_id)
{
return session_id;
}

EMSCRIPTEN_KEEPALIVE gboolean
mono_wasm_event_pipe_enable (const ep_char8_t *output_path,
uint32_t circular_buffer_size_in_mb,
const ep_char8_t *providers,
/* EventPipeSessionType session_type = EP_SESSION_TYPE_FILE, */
/* EventPipieSerializationFormat format = EP_SERIALIZATION_FORMAT_NETTRACE_V4, */
/* bool */ gboolean rundown_requested,
/* IpcStream stream = NULL, */
/* EventPipeSessionSycnhronousCallback sync_callback = NULL, */
/* void *callback_additional_data, */
MonoWasmEventPipeSessionID *out_session_id)
{
MONO_ENTER_GC_UNSAFE;
EventPipeSerializationFormat format = EP_SERIALIZATION_FORMAT_NETTRACE_V4;
EventPipeSessionType session_type = EP_SESSION_TYPE_FILE;

EventPipeSessionID session;
session = ep_enable_2 (output_path,
circular_buffer_size_in_mb,
providers,
session_type,
format,
!!rundown_requested,
/* stream */NULL,
/* callback*/ NULL,
/* callback_data*/ NULL);

if (out_session_id)
*out_session_id = ep_to_wasm_session_id (session);
MONO_EXIT_GC_UNSAFE;
return TRUE;
}

EMSCRIPTEN_KEEPALIVE gboolean
mono_wasm_event_pipe_session_start_streaming (MonoWasmEventPipeSessionID session_id)
{
MONO_ENTER_GC_UNSAFE;
ep_start_streaming (wasm_to_ep_session_id (session_id));
MONO_EXIT_GC_UNSAFE;
return TRUE;
}

EMSCRIPTEN_KEEPALIVE gboolean
mono_wasm_event_pipe_session_disable (MonoWasmEventPipeSessionID session_id)
{
MONO_ENTER_GC_UNSAFE;
ep_disable (wasm_to_ep_session_id (session_id));
MONO_EXIT_GC_UNSAFE;
return TRUE;
}

#endif /* HOST_WASM */
2 changes: 1 addition & 1 deletion src/mono/mono/metadata/threads.c
Original file line number Diff line number Diff line change
Expand Up @@ -4815,7 +4815,7 @@ ves_icall_System_Threading_Thread_StartInternal (MonoThreadObjectHandle thread_h
MonoThread *internal = MONO_HANDLE_RAW (thread_handle);
gboolean res;

#ifdef DISABLE_THREADS
#if defined (DISABLE_THREADS) || defined (DISABLE_WASM_USER_THREADS)
mono_error_set_platform_not_supported (error, "Cannot start threads on this runtime.");
return;
#endif
Expand Down
11 changes: 11 additions & 0 deletions src/mono/sample/wasm/browser-eventpipe/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
TOP=../../../../..

include ../wasm.mk

ifneq ($(AOT),)
override MSBUILD_ARGS+=/p:RunAOTCompilation=true
endif

PROJECT_NAME=Wasm.Browser.EventPipe.Sample.csproj

run: run-browser
67 changes: 67 additions & 0 deletions src/mono/sample/wasm/browser-eventpipe/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;


namespace Sample
{
public class Test
{
public static void Main(string[] args)
{
// not called. See main.js for all the interesting bits
}

private static int iterations;
private static CancellationTokenSource cts;

public static CancellationToken GetCancellationToken()
{
if (cts == null) {
cts = new CancellationTokenSource ();
}
return cts.Token;
}

[MethodImpl(MethodImplOptions.NoInlining)]
private static long recursiveFib (int n)
{
if (n < 1)
return 0;
if (n == 1)
return 1;
return recursiveFib (n - 1) + recursiveFib (n - 2);
}

public static async Task<int> StartAsyncWork()
{
CancellationToken ct = GetCancellationToken();
long b;
const int N = 35;
const long expected = 9227465;
while (true)
{
await Task.Delay(1).ConfigureAwait(false);
b = recursiveFib (N);
if (ct.IsCancellationRequested)
break;
iterations++;
}
return b == expected ? 42 : 0;
}

public static void StopWork()
{
cts.Cancel();
}

public static string GetIterationsDone()
{
return iterations.ToString();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<WasmCopyAppZipToHelixTestDir Condition="'$(ArchiveTests)' == 'true'">true</WasmCopyAppZipToHelixTestDir>
<WasmMainJSPath>main.js</WasmMainJSPath>
<DebugSymbols>true</DebugSymbols>
<DebugType>embedded</DebugType>
<WasmDebugLevel>1</WasmDebugLevel>
<WasmEnableES6>false</WasmEnableES6>
<WasmBuildNative>true</WasmBuildNative>
<GenerateRunScriptForSample Condition="'$(ArchiveTests)' == 'true'">true</GenerateRunScriptForSample>
<RunScriptCommand>$(ExecXHarnessCmd) wasm test-browser --app=. --browser=Chrome $(XHarnessBrowserPathArg) --html-file=index.html --output-directory=$(XHarnessOutput) -- $(MSBuildProjectName).dll</RunScriptCommand>
<FeatureWasmPerfTracing>true</FeatureWasmPerfTracing>
</PropertyGroup>

<ItemGroup>
<WasmExtraFilesToDeploy Include="index.html" />
<WasmExtraConfig Condition="false" Include="environment_variables" Value='
{
"MONO_LOG_LEVEL": "debug",
"MONO_LOG_MASK": "diagnostics"
}' />
</ItemGroup>

<PropertyGroup>
<_SampleProject>Wasm.Browser.CJS.Sample.csproj</_SampleProject>
</PropertyGroup>


<PropertyGroup>
<RunAnalyzers>true</RunAnalyzers>
</PropertyGroup>

<!-- set the condition to false and you will get a CA1416 errors about calls to create DiagnosticCounter instances -->
<ItemGroup Condition="true">
<!-- TODO: some .props file that automates this. Unfortunately just adding a ProjectReference to Microsoft.NET.WebAssembly.Threading.proj doesn't work - it ends up bundling the ref assemblies into the publish directory and breaking the app. -->
<!-- it's a reference assembly, but the project system doesn't know that - include it during compilation, but don't publish it -->
<ProjectReference Include="$(LibrariesProjectRoot)\System.Diagnostics.Tracing.WebAssembly.PerfTracing\ref\System.Diagnostics.Tracing.WebAssembly.PerfTracing.csproj" IncludeAssets="compile" PrivateAssets="none" ExcludeAssets="runtime" Private="false" />
</ItemGroup>

<Target Name="RunSample" DependsOnTargets="RunSampleWithBrowser" />
</Project>
20 changes: 20 additions & 0 deletions src/mono/sample/wasm/browser-eventpipe/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<!DOCTYPE html>
<!-- Licensed to the .NET Foundation under one or more agreements. -->
<!-- The .NET Foundation licenses this file to you under the MIT license. -->
<html>

<head>
<title>Sample EventPipe profile session</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>

<body>
<h3 id="header">Wasm Browser EventPipe profiling Sample</h3>
Computing Fib repeatedly: <span id="out"></span>
<script type="text/javascript" src="./dotnet.js"></script>
<script type="text/javascript" src="./dotnet.worker.js"></script>
<script type="text/javascript" src="./main.js"></script>
</body>

</html>
Loading