Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 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
103 changes: 98 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,29 @@ 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;

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