Skip to content

Commit 24e13b4

Browse files
committed
Baby steps
1 parent 79e3530 commit 24e13b4

File tree

12 files changed

+184
-11
lines changed

12 files changed

+184
-11
lines changed
+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# Tracing Android for .NET applications with built-in capabilities

Documentation/workflow/SystemProperties.md

+11
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,17 @@ categories:
171171
method execution timing which is written to a file named
172172
`methods.txt`. `timing=bare` should be used in preference to this
173173
category.
174+
* `native-tracing`
175+
Enable built-in tracing capabilities, using default settings.
176+
Tracing settings can be tuned using the [debug.mono.native-tracing](#debugmononative-tracing)
177+
property.
178+
179+
### debug.mono.native-tracing
180+
181+
[Full documentation](../guides/native-tracing.md)
182+
183+
Available options:
184+
174185

175186
#### Timing events format
176187

src/Xamarin.Android.Build.Tasks/ManifestOverlays/Tracing.xml

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools">
33
<application>
4-
<receiver android:name="mono.android.app.DumpTracingData" tools:node="replace" android:exported="true">
4+
<receiver android:name="mono.android.app.StopTracingAndDumpData" tools:node="replace" android:exported="true">
55
<intent-filter>
6-
<action android:name="mono.android.app.DUMP_TRACING_DATA"/>
6+
<action android:name="mono.android.app.STOP_TRACING_AND_DUMP_DATA"/>
77
</intent-filter>
88
</receiver>
99
</application>

src/java-runtime/java/mono/android/Runtime.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ public static native void initInternal (
3434
public static native void destroyContexts (int[] contextIDs);
3535
public static native void propagateUncaughtException (Thread javaThread, Throwable javaException);
3636
public static native void dumpTimingData ();
37-
public static native void dumpTracingData ();
37+
public static native void stopTracingAndDumpData ();
3838
}
3939

4040
final class XamarinUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
package mono.android.app;
22

3-
public class DumpTracingData extends android.content.BroadcastReceiver {
3+
public class StopTracingAndDumpData extends android.content.BroadcastReceiver {
44
@Override
55
public void onReceive (android.content.Context context, android.content.Intent intent) {
6-
mono.android.Runtime.dumpTracingData ();
6+
mono.android.Runtime.stopTracingAndDumpData ();
77
}
88
}

src/native/monodroid/mono_android_Runtime.h

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/native/monodroid/monodroid-glue-internal.hh

+7-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "cpp-util.hh"
1313
#include "xxhash.hh"
1414
#include "monodroid-dl.hh"
15+
#include "tracing.hh"
1516

1617
#include <mono/utils/mono-counters.h>
1718
#include <mono/metadata/profiler.h>
@@ -209,8 +210,9 @@ namespace xamarin::android::internal
209210

210211
void gather_bundled_assemblies (jstring_array_wrapper &runtimeApks, size_t *out_user_assemblies_count, bool have_split_apks);
211212
static bool should_register_file (const char *filename);
212-
void set_trace_options ();
213+
void set_mono_jit_trace_options ();
213214
void set_profile_options ();
215+
void initialize_native_tracing ();
214216

215217
void log_jit_event (MonoMethod *method, const char *event_name);
216218
static void jit_begin (MonoProfiler *prof, MonoMethod *method);
@@ -255,6 +257,10 @@ namespace xamarin::android::internal
255257
timing_period jit_time;
256258
FILE *jit_log;
257259
MonoProfilerHandle profiler_handle;
260+
TracingAutoStartMode tracing_auto_start_mode = TracingAutoStartMode::None;
261+
TracingAutoStopMode tracing_auto_stop_mode = TracingAutoStopMode::None;
262+
size_t tracing_start_delay_ms = 0;
263+
size_t tracing_stop_delay_ms = 0;
258264

259265
/*
260266
* If set, monodroid will spin in a loop until the debugger breaks the wait by

src/native/monodroid/monodroid-glue.cc

+107-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include <array>
2+
#include <charconv>
23
#include <cctype>
34
#include <cerrno>
45
#include <cstdarg>
@@ -1040,7 +1041,7 @@ MonodroidRuntime::set_debug_env_vars (void)
10401041
#endif /* DEBUG */
10411042

10421043
inline void
1043-
MonodroidRuntime::set_trace_options (void)
1044+
MonodroidRuntime::set_mono_jit_trace_options (void)
10441045
{
10451046
dynamic_local_string<PROPERTY_VALUE_BUFFER_LEN> value;
10461047
if (AndroidSystem::monodroid_get_system_property (SharedConstants::DEBUG_MONO_TRACE_PROPERTY, value) == 0)
@@ -1049,6 +1050,108 @@ MonodroidRuntime::set_trace_options (void)
10491050
mono_jit_set_trace_options (value.get ());
10501051
}
10511052

1053+
inline void
1054+
MonodroidRuntime::initialize_native_tracing ()
1055+
{
1056+
if (!Logger::native_tracing_enabled ()) [[likely]] {
1057+
return;
1058+
}
1059+
1060+
dynamic_local_string<PROPERTY_VALUE_BUFFER_LEN> value;
1061+
if (AndroidSystem::monodroid_get_system_property (SharedConstants::DEBUG_MONO_NATIVE_TRACING, value) == 0 || value.empty ()) {
1062+
tracing_auto_start_mode = TracingAutoStartMode::Startup;
1063+
tracing_auto_stop_mode = TracingAutoStopMode::DelayFromStart;
1064+
tracing_stop_delay_ms = TracingConstants::DEFAULT_STOP_DELAY_MS;
1065+
return;
1066+
}
1067+
1068+
constexpr std::string_view param_start_mode_startup { "start-mode=startup" };
1069+
constexpr std::string_view param_start_mode_delay { "start-mode=delay" };
1070+
constexpr std::string_view param_start_mode_justinit { "start-mode=just-init" };
1071+
1072+
constexpr std::string_view param_stop_mode_delay { "stop-mode=delay" };
1073+
constexpr std::string_view param_stop_mode_absolute_delay { "stop-mode=absolute-delay" };
1074+
1075+
constexpr std::string_view param_start_delay { "start-delay=" };
1076+
constexpr std::string_view param_stop_delay { "stop-delay=" };
1077+
1078+
string_segment param;
1079+
while (value.next_token (',', param)) {
1080+
if (param.equal (param_start_mode_startup)) {
1081+
tracing_auto_start_mode = TracingAutoStartMode::Startup;
1082+
continue;
1083+
}
1084+
1085+
if (param.equal (param_start_mode_delay)) {
1086+
tracing_auto_start_mode = TracingAutoStartMode::Delay;
1087+
tracing_start_delay_ms = TracingConstants::DEFAULT_START_DELAY_MS;
1088+
continue;
1089+
}
1090+
1091+
if (param.equal (param_start_mode_justinit)) {
1092+
tracing_auto_start_mode = TracingAutoStartMode::JustInit;
1093+
continue;
1094+
}
1095+
1096+
if (param.equal (param_stop_mode_delay)) {
1097+
tracing_auto_stop_mode = TracingAutoStopMode::DelayFromStart;
1098+
tracing_stop_delay_ms = TracingConstants::DEFAULT_STOP_DELAY_MS;
1099+
continue;
1100+
}
1101+
1102+
if (param.equal (param_stop_mode_absolute_delay)) {
1103+
tracing_auto_stop_mode = TracingAutoStopMode::AbsoluteDelay;
1104+
tracing_stop_delay_ms = TracingConstants::DEFAULT_STOP_DELAY_MS;
1105+
continue;
1106+
}
1107+
1108+
auto convert_delay = [](string_segment const& s, size_t start, size_t default_value) {
1109+
if (s.length () <= start) {
1110+
log_warn (
1111+
LOG_DEFAULT,
1112+
"Expected value in tracing setting '%s', using the default value of %zums",
1113+
s.start (),
1114+
default_value
1115+
);
1116+
return default_value;
1117+
}
1118+
1119+
size_t ret{};
1120+
auto [ptr, errorc] = std::from_chars (s.start () + start, s.start () + s.length (), ret);
1121+
if (errorc == std::errc ()) {
1122+
return ret;
1123+
}
1124+
1125+
if (errorc == std::errc::invalid_argument) {
1126+
log_warn (
1127+
LOG_DEFAULT,
1128+
"Tracing setting value is not a decimal integer: %s. Using the default value of %zums",
1129+
s.start (),
1130+
default_value
1131+
);
1132+
} else if (errorc == std::errc::result_out_of_range) {
1133+
log_warn (
1134+
LOG_DEFAULT,
1135+
"Tracing setting value exceeds the maximum allowed one (%zu): %s. Using the default value of %zums",
1136+
std::numeric_limits<size_t>::max (),
1137+
s.start (),
1138+
default_value
1139+
);
1140+
}
1141+
1142+
return default_value;
1143+
};
1144+
1145+
if (param.starts_with (param_start_delay)) {
1146+
tracing_start_delay_ms = convert_delay (param, param_start_delay.length () + 1, TracingConstants::DEFAULT_START_DELAY_MS);
1147+
}
1148+
1149+
if (param.starts_with (param_stop_delay)) {
1150+
tracing_stop_delay_ms = convert_delay (param, param_stop_delay.length () + 1, TracingConstants::DEFAULT_STOP_DELAY_MS);
1151+
}
1152+
}
1153+
}
1154+
10521155
inline void
10531156
MonodroidRuntime::set_profile_options ()
10541157
{
@@ -1428,6 +1531,7 @@ MonodroidRuntime::Java_mono_android_Runtime_initInternal (JNIEnv *env, jclass kl
14281531
mono_trace_set_level_string (mono_log_level.get ());
14291532
}
14301533

1534+
initialize_native_tracing ();
14311535
setup_mono_tracing (mono_log_mask, have_log_assembly, have_log_gc);
14321536
install_logging_handlers ();
14331537

@@ -1442,7 +1546,7 @@ MonodroidRuntime::Java_mono_android_Runtime_initInternal (JNIEnv *env, jclass kl
14421546

14431547
set_profile_options ();
14441548

1445-
set_trace_options ();
1549+
set_mono_jit_trace_options ();
14461550

14471551
#if defined (DEBUG)
14481552
debug.start_debugging_and_profiling ();
@@ -1615,7 +1719,7 @@ JNICALL Java_mono_android_Runtime_dumpTimingData ([[maybe_unused]] JNIEnv *env,
16151719
}
16161720

16171721
JNIEXPORT void
1618-
JNICALL Java_mono_android_Runtime_dumpTracingData ([[maybe_unused]] JNIEnv *env, [[maybe_unused]] jclass klass)
1722+
JNICALL Java_mono_android_Runtime_stopTracingAndDumpData ([[maybe_unused]] JNIEnv *env, [[maybe_unused]] jclass klass)
16191723
{
16201724
// TODO: implement
16211725
}

src/native/runtime-base/logger.cc

+5
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,11 @@ Logger::init_logging_categories (char*& mono_log_mask, char*& mono_log_level) no
205205
continue;
206206
}
207207

208+
if (param.starts_with ("native-tracing")) {
209+
_native_tracing_enabled = true;
210+
continue;
211+
}
212+
208213
if (param.starts_with ("timing=fast-bare")) {
209214
log_categories |= LOG_TIMING;
210215
_log_timing_categories |= LogTimingCategories::FastBare;

src/native/runtime-base/logger.hh

+7-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ namespace xamarin::android {
1818
return _log_timing_categories;
1919
}
2020

21+
static bool native_tracing_enabled () noexcept
22+
{
23+
return _native_tracing_enabled;
24+
}
25+
2126
#if defined(DEBUG)
2227
static void set_debugger_log_level (const char *level) noexcept;
2328

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

4853
private:
49-
static inline LogTimingCategories _log_timing_categories;
54+
static inline LogTimingCategories _log_timing_categories = LogTimingCategories::Default;
55+
static inline bool _native_tracing_enabled = false;
5056
#if defined(DEBUG)
5157
static inline bool _got_debugger_log_level = false;
5258
static inline int _debugger_log_level = 0;

src/native/runtime-base/shared-constants.hh

+1
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ namespace xamarin::android::internal
6161
static inline constexpr std::string_view DEBUG_MONO_SOFT_BREAKPOINTS { "debug.mono.soft_breakpoints" };
6262
static inline constexpr std::string_view DEBUG_MONO_TRACE_PROPERTY { "debug.mono.trace" };
6363
static inline constexpr std::string_view DEBUG_MONO_WREF_PROPERTY { "debug.mono.wref" };
64+
static inline constexpr std::string_view DEBUG_MONO_NATIVE_TRACING { "debug.mono.native-tracing" };
6465

6566
#if __arm__
6667
static constexpr std::string_view android_abi { "armeabi_v7a" };

src/native/tracing/tracing.hh

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#pragma once
2+
3+
#include <cstdint>
4+
5+
namespace xamarin::android {
6+
enum class TracingAutoStartMode
7+
{
8+
None,
9+
10+
// Start tracing as soon as possible at the application startup
11+
Startup,
12+
13+
// Start after an initial delay, counting from the application startup
14+
Delay,
15+
16+
// At the application startup, prepare for tracing at a later point. This is to avoid
17+
// unnecessary delays to load the tracing shared library and initialize everything.
18+
// Tracing itself will need to be started by a p/invoke or an intent.
19+
JustInit,
20+
};
21+
22+
enum class TracingAutoStopMode
23+
{
24+
None,
25+
26+
// Stop tracing after the designated delay, counted from the moment tracing was started
27+
DelayFromStart,
28+
29+
// Stop tracing after the designated delay, counting from application startup
30+
AbsoluteDelay,
31+
};
32+
33+
class TracingConstants
34+
{
35+
public:
36+
static inline constexpr size_t DEFAULT_STOP_DELAY_MS = 2000; // 2s
37+
static inline constexpr size_t DEFAULT_START_DELAY_MS = 0;
38+
};
39+
}

0 commit comments

Comments
 (0)