Skip to content

Commit 118284a

Browse files
committed
Baby steps
1 parent 1b91713 commit 118284a

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
@@ -35,7 +35,7 @@ public static native void initInternal (
3535
public static native void destroyContexts (int[] contextIDs);
3636
public static native void propagateUncaughtException (Thread javaThread, Throwable javaException);
3737
public static native void dumpTimingData ();
38-
public static native void dumpTracingData ();
38+
public static native void stopTracingAndDumpData ();
3939
}
4040

4141
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>
@@ -214,8 +215,9 @@ namespace xamarin::android::internal
214215

215216
void gather_bundled_assemblies (jstring_array_wrapper &runtimeApks, size_t *out_user_assemblies_count, bool have_split_apks);
216217
static bool should_register_file (const char *filename);
217-
void set_trace_options ();
218+
void set_mono_jit_trace_options ();
218219
void set_profile_options ();
220+
void initialize_native_tracing ();
219221

220222
void log_jit_event (MonoMethod *method, const char *event_name);
221223
static void jit_begin (MonoProfiler *prof, MonoMethod *method);
@@ -261,6 +263,10 @@ namespace xamarin::android::internal
261263
timing_period jit_time;
262264
FILE *jit_log;
263265
MonoProfilerHandle profiler_handle;
266+
TracingAutoStartMode tracing_auto_start_mode = TracingAutoStartMode::None;
267+
TracingAutoStopMode tracing_auto_stop_mode = TracingAutoStopMode::None;
268+
size_t tracing_start_delay_ms = 0;
269+
size_t tracing_stop_delay_ms = 0;
264270

265271
/*
266272
* 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>
@@ -1057,7 +1058,7 @@ MonodroidRuntime::set_debug_env_vars (void)
10571058
#endif /* DEBUG */
10581059

10591060
inline void
1060-
MonodroidRuntime::set_trace_options (void)
1061+
MonodroidRuntime::set_mono_jit_trace_options (void)
10611062
{
10621063
dynamic_local_string<PROPERTY_VALUE_BUFFER_LEN> value;
10631064
if (AndroidSystem::monodroid_get_system_property (SharedConstants::DEBUG_MONO_TRACE_PROPERTY, value) == 0)
@@ -1066,6 +1067,108 @@ MonodroidRuntime::set_trace_options (void)
10661067
mono_jit_set_trace_options (value.get ());
10671068
}
10681069

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

1552+
initialize_native_tracing ();
14491553
setup_mono_tracing (mono_log_mask, have_log_assembly, have_log_gc);
14501554
install_logging_handlers ();
14511555

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

14611565
set_profile_options ();
14621566

1463-
set_trace_options ();
1567+
set_mono_jit_trace_options ();
14641568

14651569
#if defined (DEBUG)
14661570
debug.start_debugging_and_profiling ();
@@ -1635,7 +1739,7 @@ JNICALL Java_mono_android_Runtime_dumpTimingData ([[maybe_unused]] JNIEnv *env,
16351739
}
16361740

16371741
JNIEXPORT void
1638-
JNICALL Java_mono_android_Runtime_dumpTracingData ([[maybe_unused]] JNIEnv *env, [[maybe_unused]] jclass klass)
1742+
JNICALL Java_mono_android_Runtime_stopTracingAndDumpData ([[maybe_unused]] JNIEnv *env, [[maybe_unused]] jclass klass)
16391743
{
16401744
// TODO: implement
16411745
}

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)