Skip to content

Commit

Permalink
Baby steps
Browse files Browse the repository at this point in the history
  • Loading branch information
grendello committed Jul 26, 2024
1 parent 1b91713 commit 118284a
Show file tree
Hide file tree
Showing 12 changed files with 184 additions and 11 deletions.
1 change: 1 addition & 0 deletions Documentation/guides/native-tracing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Tracing Android for .NET applications with built-in capabilities
11 changes: 11 additions & 0 deletions Documentation/workflow/SystemProperties.md
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,17 @@ categories:
method execution timing which is written to a file named
`methods.txt`. `timing=bare` should be used in preference to this
category.
* `native-tracing`
Enable built-in tracing capabilities, using default settings.
Tracing settings can be tuned using the [debug.mono.native-tracing](#debugmononative-tracing)
property.

### debug.mono.native-tracing

[Full documentation](../guides/native-tracing.md)

Available options:


#### Timing events format

Expand Down
4 changes: 2 additions & 2 deletions src/Xamarin.Android.Build.Tasks/ManifestOverlays/Tracing.xml
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools">
<application>
<receiver android:name="mono.android.app.DumpTracingData" tools:node="replace" android:exported="true">
<receiver android:name="mono.android.app.StopTracingAndDumpData" tools:node="replace" android:exported="true">
<intent-filter>
<action android:name="mono.android.app.DUMP_TRACING_DATA"/>
<action android:name="mono.android.app.STOP_TRACING_AND_DUMP_DATA"/>
</intent-filter>
</receiver>
</application>
Expand Down
2 changes: 1 addition & 1 deletion src/java-runtime/java/mono/android/Runtime.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public static native void initInternal (
public static native void destroyContexts (int[] contextIDs);
public static native void propagateUncaughtException (Thread javaThread, Throwable javaException);
public static native void dumpTimingData ();
public static native void dumpTracingData ();
public static native void stopTracingAndDumpData ();
}

final class XamarinUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package mono.android.app;

public class DumpTracingData extends android.content.BroadcastReceiver {
public class StopTracingAndDumpData extends android.content.BroadcastReceiver {
@Override
public void onReceive (android.content.Context context, android.content.Intent intent) {
mono.android.Runtime.dumpTracingData ();
mono.android.Runtime.stopTracingAndDumpData ();
}
}
2 changes: 1 addition & 1 deletion src/native/monodroid/mono_android_Runtime.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 7 additions & 1 deletion src/native/monodroid/monodroid-glue-internal.hh
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "cpp-util.hh"
#include "xxhash.hh"
#include "monodroid-dl.hh"
#include "tracing.hh"

#include <mono/utils/mono-counters.h>
#include <mono/metadata/profiler.h>
Expand Down Expand Up @@ -214,8 +215,9 @@ namespace xamarin::android::internal

void gather_bundled_assemblies (jstring_array_wrapper &runtimeApks, size_t *out_user_assemblies_count, bool have_split_apks);
static bool should_register_file (const char *filename);
void set_trace_options ();
void set_mono_jit_trace_options ();
void set_profile_options ();
void initialize_native_tracing ();

void log_jit_event (MonoMethod *method, const char *event_name);
static void jit_begin (MonoProfiler *prof, MonoMethod *method);
Expand Down Expand Up @@ -261,6 +263,10 @@ namespace xamarin::android::internal
timing_period jit_time;
FILE *jit_log;
MonoProfilerHandle profiler_handle;
TracingAutoStartMode tracing_auto_start_mode = TracingAutoStartMode::None;
TracingAutoStopMode tracing_auto_stop_mode = TracingAutoStopMode::None;
size_t tracing_start_delay_ms = 0;
size_t tracing_stop_delay_ms = 0;

/*
* If set, monodroid will spin in a loop until the debugger breaks the wait by
Expand Down
110 changes: 107 additions & 3 deletions src/native/monodroid/monodroid-glue.cc
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <array>
#include <charconv>
#include <cctype>
#include <cerrno>
#include <cstdarg>
Expand Down Expand Up @@ -1057,7 +1058,7 @@ MonodroidRuntime::set_debug_env_vars (void)
#endif /* DEBUG */

inline void
MonodroidRuntime::set_trace_options (void)
MonodroidRuntime::set_mono_jit_trace_options (void)
{
dynamic_local_string<PROPERTY_VALUE_BUFFER_LEN> value;
if (AndroidSystem::monodroid_get_system_property (SharedConstants::DEBUG_MONO_TRACE_PROPERTY, value) == 0)
Expand All @@ -1066,6 +1067,108 @@ MonodroidRuntime::set_trace_options (void)
mono_jit_set_trace_options (value.get ());
}

inline void
MonodroidRuntime::initialize_native_tracing ()
{
if (!Logger::native_tracing_enabled ()) [[likely]] {
return;
}

dynamic_local_string<PROPERTY_VALUE_BUFFER_LEN> value;
if (AndroidSystem::monodroid_get_system_property (SharedConstants::DEBUG_MONO_NATIVE_TRACING, value) == 0 || value.empty ()) {
tracing_auto_start_mode = TracingAutoStartMode::Startup;
tracing_auto_stop_mode = TracingAutoStopMode::DelayFromStart;
tracing_stop_delay_ms = TracingConstants::DEFAULT_STOP_DELAY_MS;
return;
}

constexpr std::string_view param_start_mode_startup { "start-mode=startup" };
constexpr std::string_view param_start_mode_delay { "start-mode=delay" };
constexpr std::string_view param_start_mode_justinit { "start-mode=just-init" };

constexpr std::string_view param_stop_mode_delay { "stop-mode=delay" };
constexpr std::string_view param_stop_mode_absolute_delay { "stop-mode=absolute-delay" };

constexpr std::string_view param_start_delay { "start-delay=" };
constexpr std::string_view param_stop_delay { "stop-delay=" };

string_segment param;
while (value.next_token (',', param)) {
if (param.equal (param_start_mode_startup)) {
tracing_auto_start_mode = TracingAutoStartMode::Startup;
continue;
}

if (param.equal (param_start_mode_delay)) {
tracing_auto_start_mode = TracingAutoStartMode::Delay;
tracing_start_delay_ms = TracingConstants::DEFAULT_START_DELAY_MS;
continue;
}

if (param.equal (param_start_mode_justinit)) {
tracing_auto_start_mode = TracingAutoStartMode::JustInit;
continue;
}

if (param.equal (param_stop_mode_delay)) {
tracing_auto_stop_mode = TracingAutoStopMode::DelayFromStart;
tracing_stop_delay_ms = TracingConstants::DEFAULT_STOP_DELAY_MS;
continue;
}

if (param.equal (param_stop_mode_absolute_delay)) {
tracing_auto_stop_mode = TracingAutoStopMode::AbsoluteDelay;
tracing_stop_delay_ms = TracingConstants::DEFAULT_STOP_DELAY_MS;
continue;
}

auto convert_delay = [](string_segment const& s, size_t start, size_t default_value) {
if (s.length () <= start) {
log_warn (
LOG_DEFAULT,
"Expected value in tracing setting '%s', using the default value of %zums",
s.start (),
default_value
);
return default_value;
}

size_t ret{};
auto [ptr, errorc] = std::from_chars (s.start () + start, s.start () + s.length (), ret);
if (errorc == std::errc ()) {
return ret;
}

if (errorc == std::errc::invalid_argument) {
log_warn (
LOG_DEFAULT,
"Tracing setting value is not a decimal integer: %s. Using the default value of %zums",
s.start (),
default_value
);
} else if (errorc == std::errc::result_out_of_range) {
log_warn (
LOG_DEFAULT,
"Tracing setting value exceeds the maximum allowed one (%zu): %s. Using the default value of %zums",
std::numeric_limits<size_t>::max (),
s.start (),
default_value
);
}

return default_value;
};

if (param.starts_with (param_start_delay)) {
tracing_start_delay_ms = convert_delay (param, param_start_delay.length () + 1, TracingConstants::DEFAULT_START_DELAY_MS);
}

if (param.starts_with (param_stop_delay)) {
tracing_stop_delay_ms = convert_delay (param, param_stop_delay.length () + 1, TracingConstants::DEFAULT_STOP_DELAY_MS);
}
}
}

inline void
MonodroidRuntime::set_profile_options ()
{
Expand Down Expand Up @@ -1446,6 +1549,7 @@ MonodroidRuntime::Java_mono_android_Runtime_initInternal (JNIEnv *env, jclass kl
mono_trace_set_level_string (mono_log_level.get ());
}

initialize_native_tracing ();
setup_mono_tracing (mono_log_mask, have_log_assembly, have_log_gc);
install_logging_handlers ();

Expand All @@ -1460,7 +1564,7 @@ MonodroidRuntime::Java_mono_android_Runtime_initInternal (JNIEnv *env, jclass kl

set_profile_options ();

set_trace_options ();
set_mono_jit_trace_options ();

#if defined (DEBUG)
debug.start_debugging_and_profiling ();
Expand Down Expand Up @@ -1635,7 +1739,7 @@ JNICALL Java_mono_android_Runtime_dumpTimingData ([[maybe_unused]] JNIEnv *env,
}

JNIEXPORT void
JNICALL Java_mono_android_Runtime_dumpTracingData ([[maybe_unused]] JNIEnv *env, [[maybe_unused]] jclass klass)
JNICALL Java_mono_android_Runtime_stopTracingAndDumpData ([[maybe_unused]] JNIEnv *env, [[maybe_unused]] jclass klass)
{
// TODO: implement
}
Expand Down
5 changes: 5 additions & 0 deletions src/native/runtime-base/logger.cc
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,11 @@ Logger::init_logging_categories (char*& mono_log_mask, char*& mono_log_level) no
continue;
}

if (param.starts_with ("native-tracing")) {
_native_tracing_enabled = true;
continue;
}

if (param.starts_with ("timing=fast-bare")) {
log_categories |= LOG_TIMING;
_log_timing_categories |= LogTimingCategories::FastBare;
Expand Down
8 changes: 7 additions & 1 deletion src/native/runtime-base/logger.hh
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ namespace xamarin::android {
return _log_timing_categories;
}

static bool native_tracing_enabled () noexcept
{
return _native_tracing_enabled;
}

#if defined(DEBUG)
static void set_debugger_log_level (const char *level) noexcept;

Expand Down Expand Up @@ -46,7 +51,8 @@ namespace xamarin::android {
static bool set_category (std::string_view const& name, internal::string_segment& arg, unsigned int entry, bool arg_starts_with_name = false) noexcept;

private:
static inline LogTimingCategories _log_timing_categories;
static inline LogTimingCategories _log_timing_categories = LogTimingCategories::Default;
static inline bool _native_tracing_enabled = false;
#if defined(DEBUG)
static inline bool _got_debugger_log_level = false;
static inline int _debugger_log_level = 0;
Expand Down
1 change: 1 addition & 0 deletions src/native/runtime-base/shared-constants.hh
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ namespace xamarin::android::internal
static inline constexpr std::string_view DEBUG_MONO_SOFT_BREAKPOINTS { "debug.mono.soft_breakpoints" };
static inline constexpr std::string_view DEBUG_MONO_TRACE_PROPERTY { "debug.mono.trace" };
static inline constexpr std::string_view DEBUG_MONO_WREF_PROPERTY { "debug.mono.wref" };
static inline constexpr std::string_view DEBUG_MONO_NATIVE_TRACING { "debug.mono.native-tracing" };

#if __arm__
static constexpr std::string_view android_abi { "armeabi_v7a" };
Expand Down
39 changes: 39 additions & 0 deletions src/native/tracing/tracing.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#pragma once

#include <cstdint>

namespace xamarin::android {
enum class TracingAutoStartMode
{
None,

// Start tracing as soon as possible at the application startup
Startup,

// Start after an initial delay, counting from the application startup
Delay,

// At the application startup, prepare for tracing at a later point. This is to avoid
// unnecessary delays to load the tracing shared library and initialize everything.
// Tracing itself will need to be started by a p/invoke or an intent.
JustInit,
};

enum class TracingAutoStopMode
{
None,

// Stop tracing after the designated delay, counted from the moment tracing was started
DelayFromStart,

// Stop tracing after the designated delay, counting from application startup
AbsoluteDelay,
};

class TracingConstants
{
public:
static inline constexpr size_t DEFAULT_STOP_DELAY_MS = 2000; // 2s
static inline constexpr size_t DEFAULT_START_DELAY_MS = 0;
};
}

0 comments on commit 118284a

Please sign in to comment.