Skip to content
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
2 changes: 0 additions & 2 deletions src/mono/browser/browser.proj
Original file line number Diff line number Diff line change
Expand Up @@ -576,8 +576,6 @@
<_MonoRollupEnvironmentVariable Include="WasmEnableThreads:$(WasmEnableThreads)" />
<_MonoRollupEnvironmentVariable Include="WASM_ENABLE_SIMD:1" Condition="'$(WasmEnableSIMD)' != 'false'" />
<_MonoRollupEnvironmentVariable Include="WASM_ENABLE_SIMD:0" Condition="'$(WasmEnableSIMD)' == 'false'" />
<_MonoRollupEnvironmentVariable Include="WASM_PERFTRACING:1" Condition="'$(WasmPerfTracing)' == 'true'" />
<_MonoRollupEnvironmentVariable Include="WASM_PERFTRACING:0" Condition="'$(WasmPerfTracing)' != 'true'" />
<_MonoRollupEnvironmentVariable Include="WASM_ENABLE_EH:1" Condition="'$(WasmEnableExceptionHandling)' != 'false'" />
<_MonoRollupEnvironmentVariable Include="WASM_ENABLE_EH:0" Condition="'$(WasmEnableExceptionHandling)' == 'false'" />
<_MonoRollupEnvironmentVariable Include="ENABLE_JS_INTEROP_BY_VALUE:1" Condition="'$(WasmEnableJsInteropByValue)' == 'true'" />
Expand Down
1 change: 1 addition & 0 deletions src/mono/browser/build/BrowserWasmApp.targets
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@
<WasmExtraFilesToDeploy Include="$(WasmMainHTMLPath)" Condition="'$(WasmMainHTMLPath)' != ''" />
<WasmExtraFilesToDeploy Include="$(WasmMainJSPath)" Condition="'$(WasmMainJSPath)' != ''" />
<WasmEnvironmentVariable Include="DOTNET_DiagnosticPorts" Value="$(DiagnosticPorts)" Condition="'$(DiagnosticPorts)' != ''"/>
<WasmEnvironmentVariable Include="DOTNET_WasmPerfInstrumentation" Value="1" Condition="'$(WasmPerfInstrumentation)' == 'true'"/>
</ItemGroup>

<RemoveDir Directories="$(WasmAppDir)" />
Expand Down
11 changes: 8 additions & 3 deletions src/mono/browser/runtime/diagnostics/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

import type { GlobalObjects } from "../types/internal";
import type { GlobalObjects, MonoMethod } from "../types/internal";
import type { CharPtr, VoidPtr } from "../types/emscripten";

import { diagnosticHelpers, setRuntimeGlobalsImpl } from "./globals";
import { diagnosticHelpers, runtimeHelpers, setRuntimeGlobalsImpl } from "./globals";

/* eslint-disable @typescript-eslint/no-unused-vars */
export function setRuntimeGlobals (globalObjects: GlobalObjects): void {
Expand All @@ -30,8 +30,13 @@ export function setRuntimeGlobals (globalObjects: GlobalObjects): void {
return 0;
};

diagnosticHelpers. ds_rt_websocket_close = (client_socket :number):number => {
diagnosticHelpers.ds_rt_websocket_close = (client_socket :number):number => {
// Not implemented yet
return 0;
};
runtimeHelpers.mono_wasm_instrument_method = (method: MonoMethod): number => {
const environmentVariables = runtimeHelpers.config.environmentVariables || {};
const value = environmentVariables["DOTNET_WasmPerfInstrumentation"];
return (value == "1" || value == "true") ? 1 : 0;
};
}
13 changes: 6 additions & 7 deletions src/mono/browser/runtime/driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -534,17 +534,16 @@ EMSCRIPTEN_KEEPALIVE const char * mono_wasm_method_get_name (MonoMethod *method)
return res;
}

EMSCRIPTEN_KEEPALIVE const char * mono_wasm_method_get_name_ex (MonoMethod *method) {
const char *res;
EMSCRIPTEN_KEEPALIVE char * mono_wasm_method_get_name_ex (MonoMethod *method) {
char *res;
MONO_ENTER_GC_UNSAFE;
res = mono_method_get_name (method);
const char *method_name = mono_method_get_name (method);
// starts with .ctor or .cctor
if (mono_method_get_flags (method, NULL) & 0x0800 /* METHOD_ATTRIBUTE_SPECIAL_NAME */ && strlen (res) < 7) {
char *res_ex = (char *) malloc (128);
snprintf (res_ex, 128,"%s.%s", mono_class_get_name (mono_method_get_class (method)), res);
res = res_ex;
res = (char *) malloc (128);
snprintf (res, 128,"%s.%s", mono_class_get_name (mono_method_get_class (method)), method_name);
} else {
res = strdup (res);
res = strdup (method_name);
}
MONO_EXIT_GC_UNSAFE;
return res;
Expand Down
5 changes: 3 additions & 2 deletions src/mono/browser/runtime/exports-binding.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import { mono_wasm_dump_threads } from "./pthreads/ui-thread";
import { mono_wasm_schedule_synchronization_context } from "./pthreads/shared";
import { mono_wasm_get_locale_info } from "./globalization-locale";

import { mono_wasm_profiler_record, mono_wasm_profiler_now } from "./profiler";
import { mono_wasm_profiler_record, mono_wasm_profiler_now, mono_wasm_instrument_method } from "./profiler";
import { ds_rt_websocket_create, ds_rt_websocket_send, ds_rt_websocket_poll, ds_rt_websocket_recv, ds_rt_websocket_close } from "./diagnostics";

// the JS methods would be visible to EMCC linker and become imports of the WASM module
Expand Down Expand Up @@ -72,7 +72,8 @@ export const mono_wasm_imports = [
mono_interp_flush_jitcall_queue,
mono_wasm_free_method_data,

// browser.c
// browser.c, ep-rt-mono-runtime-provider.c
mono_wasm_instrument_method,
mono_wasm_profiler_now,
mono_wasm_profiler_record,

Expand Down
3 changes: 3 additions & 0 deletions src/mono/browser/runtime/jiterpreter-trace-generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1422,9 +1422,12 @@ export function generateWasmBody (
// call C
case MintOpcode.MINT_PROF_ENTER:
case MintOpcode.MINT_PROF_SAMPLEPOINT:
append_profiler_event(builder, ip, opcode);
break;
case MintOpcode.MINT_PROF_EXIT:
case MintOpcode.MINT_PROF_EXIT_VOID:
append_profiler_event(builder, ip, opcode);
ip = abort;
break;

// Generating code for these is kind of complex due to the intersection of JS and int64,
Expand Down
2 changes: 1 addition & 1 deletion src/mono/browser/runtime/jiterpreter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1084,7 +1084,7 @@ export function mono_interp_tier_prepare_jiterpreter (
export function mono_wasm_free_method_data (
method: MonoMethod, imethod: number, traceIndex: number
) {
if (runtimeHelpers.emscriptenBuildOptions.enablePerfTracing) {
if (runtimeHelpers.emscriptenBuildOptions.enableBrowserProfiler) {
mono_wasm_profiler_free_method(method);
}

Expand Down
4 changes: 4 additions & 0 deletions src/mono/browser/runtime/profiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,3 +119,7 @@ export function mono_wasm_profiler_record (method: MonoMethod, start: number): v
}
globalThis.performance.measure(methodName, options);
}

export function mono_wasm_instrument_method (method:MonoMethod):number {
return runtimeHelpers.mono_wasm_instrument_method(method);
}
5 changes: 3 additions & 2 deletions src/mono/browser/runtime/types/internal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -244,8 +244,9 @@ export type RuntimeHelpers = {
dumpThreads: () => void,
mono_wasm_print_thread_dump: () => void,
utf8ToString: (ptr: CharPtr) => string,
mono_background_exec: () =>void;
mono_wasm_ds_exec: () =>void;
mono_background_exec: () => void;
mono_wasm_ds_exec: () => void,
mono_wasm_instrument_method: (method:MonoMethod) => number,
}

export type DiagnosticHelpers = {
Expand Down
105 changes: 100 additions & 5 deletions src/mono/mono/eventpipe/ep-rt-mono-runtime-provider.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <eventpipe/ep-types.h>
#include <eventpipe/ep-rt.h>
#include <eventpipe/ep.h>
#include <eventpipe/ep-sample-profiler.h>

#include <eglib/gmodule.h>
#include <mono/metadata/profiler.h>
Expand Down Expand Up @@ -1340,15 +1341,17 @@ ep_rt_mono_sample_profiler_write_sampling_event_for_threads (
}

static void
method_enter (MonoProfiler *prof, MonoMethod *method, MonoProfilerCallContext *ctx)
sample_current_thread_stack_trace ()
{
MonoContext ctx;
MonoThreadInfo *thread_info = mono_thread_info_current ();
SampleProfileStackWalkData stack_walk_data;
SampleProfileStackWalkData *data= &stack_walk_data;
THREAD_INFO_TYPE adapter = { { 0 } };
MONO_INIT_CONTEXT_FROM_FUNC (&ctx, sample_current_thread_stack_trace);

data->thread_id = ep_rt_thread_id_t_to_uint64_t (mono_thread_info_get_tid (thread_info));
data->thread_ip = (uintptr_t)MONO_CONTEXT_GET_IP (&ctx->context);
data->thread_ip = (uintptr_t)MONO_CONTEXT_GET_IP (&ctx);
data->payload_data = EP_SAMPLE_PROFILER_SAMPLE_TYPE_ERROR;
data->stack_walk_data.stack_contents = &data->stack_contents;
data->stack_walk_data.top_frame = true;
Expand All @@ -1357,7 +1360,8 @@ method_enter (MonoProfiler *prof, MonoMethod *method, MonoProfilerCallContext *c
data->stack_walk_data.runtime_invoke_frame = false;
ep_stack_contents_reset (&data->stack_contents);

mono_get_eh_callbacks ()->mono_walk_stack_with_ctx (sample_profiler_walk_managed_stack_for_thread_callback, &ctx->context, MONO_UNWIND_NONE, &stack_walk_data);
// because this is single threaded, MONO_UNWIND_NONE is safe to use
mono_get_eh_callbacks ()->mono_walk_stack_with_ctx (sample_profiler_walk_managed_stack_for_thread_callback, &ctx, MONO_UNWIND_NONE, &stack_walk_data);
if (data->payload_data == EP_SAMPLE_PROFILER_SAMPLE_TYPE_EXTERNAL && (data->stack_walk_data.safe_point_frame || data->stack_walk_data.runtime_invoke_frame)) {
data->payload_data = EP_SAMPLE_PROFILER_SAMPLE_TYPE_MANAGED;
}
Expand All @@ -1376,13 +1380,90 @@ method_enter (MonoProfiler *prof, MonoMethod *method, MonoProfilerCallContext *c
}
}

static double desired_sample_interval_ms;

static double last_sample_time;
static int prev_skips_per_period;
static int skips_per_period;
static int sample_skip_counter;

#ifdef HOST_BROWSER
double mono_wasm_profiler_now ();
static double profiler_now ()
{
return mono_wasm_profiler_now ();
}
#else
#error "Not implemented"
#endif

static void update_sample_frequency ()
{
// timer resolution in non-isolated contexts: 100 microseconds (decimal number)
double now = profiler_now ();
double ms_since_last_sample = now - last_sample_time;

if (desired_sample_interval_ms > 0 && last_sample_time != 0) {
// recalculate ideal number of skips per period
double skips_per_ms = ((double)sample_skip_counter) / ms_since_last_sample;
double newskips_per_period = (skips_per_ms * ((double)desired_sample_interval_ms));
skips_per_period = ((newskips_per_period + ((double)sample_skip_counter) + ((double)prev_skips_per_period)) / 3);
prev_skips_per_period = sample_skip_counter;
} else {
skips_per_period = 0;
}
last_sample_time = now;
sample_skip_counter = 0;
}

static void
method_enter (MonoProfiler *prof, MonoMethod *method, MonoProfilerCallContext *ctx)
{
sample_skip_counter++;
if (G_LIKELY(sample_skip_counter < skips_per_period))
return;
update_sample_frequency ();
sample_current_thread_stack_trace ();
}

static void
method_samplepoint (MonoProfiler *prof, MonoMethod *method, MonoProfilerCallContext *ctx)
{
sample_skip_counter++;
if (G_LIKELY(sample_skip_counter < skips_per_period))
return;
update_sample_frequency ();
sample_current_thread_stack_trace ();
}

static void
method_exc_leave (MonoProfiler *prof, MonoMethod *method, MonoObject *exc)
{
sample_skip_counter++;
if (G_LIKELY(sample_skip_counter < skips_per_period))
return;
update_sample_frequency ();
sample_current_thread_stack_trace ();
}

#ifdef HOST_BROWSER
int mono_wasm_instrument_method ();

static MonoProfilerCallInstrumentationFlags
method_filter (MonoProfiler *prof, MonoMethod *method)
{
// TODO add more instrumentation, something like MINT_SDB_SEQ_POINT
return MONO_PROFILER_CALL_INSTRUMENTATION_ENTER;
if (!mono_wasm_instrument_method (method)){
return MONO_PROFILER_CALL_INSTRUMENTATION_NONE;
}

return MONO_PROFILER_CALL_INSTRUMENTATION_SAMPLEPOINT |
MONO_PROFILER_CALL_INSTRUMENTATION_ENTER |
MONO_PROFILER_CALL_INSTRUMENTATION_EXCEPTION_LEAVE;
}

#else
#error "Not implemented"
#endif

void
ep_rt_mono_sampling_provider_component_init (void)
Expand All @@ -1404,17 +1485,31 @@ ep_rt_mono_sampling_provider_component_fini (void)
void
ep_rt_mono_sample_profiler_enabled (EventPipeEvent *sampling_event)
{
desired_sample_interval_ms = ((double)ep_sample_profiler_get_sampling_rate ()) / 1000000.0;
EP_ASSERT (desired_sample_interval_ms >= 0.0);
EP_ASSERT (desired_sample_interval_ms < 1000.0);

current_sampling_event = sampling_event;
current_sampling_thread = ep_rt_thread_get_handle ();
EP_ASSERT (_ep_rt_mono_sampling_profiler_provider != NULL);

last_sample_time = 0;
prev_skips_per_period = 1;
skips_per_period = 1;
sample_skip_counter = 1;

mono_profiler_set_method_samplepoint_callback (_ep_rt_mono_sampling_profiler_provider, method_samplepoint);
mono_profiler_set_method_enter_callback (_ep_rt_mono_sampling_profiler_provider, method_enter);
mono_profiler_set_method_exception_leave_callback (_ep_rt_mono_sampling_profiler_provider, method_exc_leave);
}

void
ep_rt_mono_sample_profiler_disabled (void)
{
EP_ASSERT (_ep_rt_mono_sampling_profiler_provider != NULL);
mono_profiler_set_method_samplepoint_callback (_ep_rt_mono_sampling_profiler_provider, NULL);
mono_profiler_set_method_enter_callback (_ep_rt_mono_sampling_profiler_provider, NULL);
mono_profiler_set_method_exception_leave_callback (_ep_rt_mono_sampling_profiler_provider, NULL);
}

#endif // PERFTRACING_DISABLE_THREADS
Expand Down
1 change: 1 addition & 0 deletions src/mono/mono/eventpipe/ep-rt-mono.h
Original file line number Diff line number Diff line change
Expand Up @@ -776,6 +776,7 @@ inline
void
ep_rt_wait_event_free (ep_rt_wait_event_handle_t *wait_event)
{
wait_event->event = NULL;
}

static
Expand Down
2 changes: 1 addition & 1 deletion src/mono/mono/eventpipe/test/ep-buffer-manager-tests.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ buffer_manager_fini (

// buffer_manager owned by session.
EP_ASSERT (buffer_manager == NULL || buffer_manager == ep_session_get_buffer_manager (session));
ep_session_free (session);
ep_session_dec_ref (session);
}

static
Expand Down
2 changes: 1 addition & 1 deletion src/mono/mono/eventpipe/test/ep-buffer-tests.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ load_buffer_with_events_fini (
{
ep_event_free (ep_event);
ep_delete_provider (provider);
ep_session_free (session);
ep_session_dec_ref (session);
}

static
Expand Down
6 changes: 3 additions & 3 deletions src/mono/mono/eventpipe/test/ep-session-tests.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ test_create_delete_session (void)
ep_raise_error_if_nok (test_session != NULL);

ep_on_exit:
ep_session_free (test_session);
ep_session_dec_ref (test_session);
ep_provider_config_fini (current_provider_config);
return result;

Expand Down Expand Up @@ -141,7 +141,7 @@ test_add_session_providers (void)
EP_LOCK_EXIT (section5)

ep_on_exit:
ep_session_free (test_session);
ep_session_dec_ref (test_session);
ep_provider_config_fini (current_provider_config);
return result;

Expand Down Expand Up @@ -230,7 +230,7 @@ test_session_special_get_set (void)
}

ep_on_exit:
ep_session_free (test_session);
ep_session_dec_ref (test_session);
ep_provider_config_fini (current_provider_config);
return result;

Expand Down
2 changes: 1 addition & 1 deletion src/mono/mono/eventpipe/test/ep-thread-tests.c
Original file line number Diff line number Diff line change
Expand Up @@ -446,7 +446,7 @@ test_thread_session_state (void)
ep_thread_delete_session_state (thread, session);
ep_rt_spin_lock_release (ep_thread_get_rt_lock_ref (thread));
}
ep_session_free (session);
ep_session_dec_ref (session);
ep_provider_config_fini (provider_config);
ep_thread_release (thread);
return result;
Expand Down
Loading
Loading