Skip to content

Conversation

@jonathanpeppers
Copy link
Member

Context: https://github.com/mono/mono/blob/42c5ccc298c9b1b5f78781f5db4dab51ebacb522/mcs/class/corlib/Assembly/AssemblyInfo.cs#L84-L93

If we lived in a world where mscorlib.dll has InternalsVisibleTo
for Mono.Android, we can remove some System.Reflection that gets
called on startup.

We need to be able to call these methods directly:

  • System.Diagnostics.Debugger.Mono_UnhandledException
  • AppDomain.CurrentDomain.DoUnhandledException

The only other change is that some files need:

using LogLevel = Android.Runtime.LogLevel;

There is an internal System.LogLevel that we need to disambiguate.

NOTE: this won't fully work until the change in Mono lands.

Results

I tested the Xamarin.Forms integration project, using a Debug build on
a HAXM x86 emulator on Windows.

The reason I looked into this, is I initially saw a log message like:

12-03 14:28:11.969 27129 27129 I monodroid-timing: Runtime.register: registered type 'Android.Runtime.UncaughtExceptionHandler, Mono.Android'
12-03 14:28:11.969 27129 27129 I monodroid-timing: Runtime.register: end time; elapsed: 0s:79::609300

After the change, it is more like:

12-04 09:13:32.944  9758  9758 I monodroid-timing: Runtime.register: registered type 'Android.Runtime.UncaughtExceptionHandler, Mono.Android'
12-04 09:13:32.944  9758  9758 I monodroid-timing: Runtime.register: end time; elapsed: 0s:73::727800

However, if I look at the total Runtime.init time:

Before:
12-03 14:27:48.494 26903 26903 I monodroid-timing: Runtime.init: end, total time; elapsed: 0s:601::443900
12-03 14:27:54.356 26963 26963 I monodroid-timing: Runtime.init: end, total time; elapsed: 0s:587::495400
12-03 14:28:00.263 27021 27021 I monodroid-timing: Runtime.init: end, total time; elapsed: 0s:586::147100
12-03 14:28:06.135 27074 27074 I monodroid-timing: Runtime.init: end, total time; elapsed: 0s:593::639100
12-03 14:28:11.988 27129 27129 I monodroid-timing: Runtime.init: end, total time; elapsed: 0s:571::194900
After:
12-04 09:13:15.386  9587  9587 I monodroid-timing: Runtime.init: end, total time; elapsed: 0s:584::909700
12-04 09:13:21.179  9644  9644 I monodroid-timing: Runtime.init: end, total time; elapsed: 0s:506::64600
12-04 09:13:27.148  9699  9699 I monodroid-timing: Runtime.init: end, total time; elapsed: 0s:560::98500
12-04 09:13:32.963  9758  9758 I monodroid-timing: Runtime.init: end, total time; elapsed: 0s:504::939400
12-04 09:13:38.887  9814  9814 I monodroid-timing: Runtime.init: end, total time; elapsed: 0s:531::234100

And then the total activity time:

Before:
12-03 14:27:51.450  1876  1898 I ActivityManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +3s727ms
12-03 14:27:57.310  1876  1898 I ActivityManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +3s723ms
12-03 14:28:03.216  1876  1898 I ActivityManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +3s703ms
12-03 14:28:09.054  1876  1898 I ActivityManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +3s679ms
12-03 14:28:14.953  1876  1898 I ActivityManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +3s711ms
After:
12-04 09:13:18.248  1876  1898 I ActivityManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +3s608ms
12-04 09:13:24.087  1876  1898 I ActivityManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +3s570ms
12-04 09:13:29.997  1876  1898 I ActivityManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +3s566ms
12-04 09:13:35.805  1876  1898 I ActivityManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +3s498ms
12-04 09:13:41.670  1876  1898 I ActivityManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +3s475ms

It seems like this might be saving us as much as ~250ms to the total
startup on a HAXM emulator in Debug mode?

…dler

Context: https://github.com/mono/mono/blob/42c5ccc298c9b1b5f78781f5db4dab51ebacb522/mcs/class/corlib/Assembly/AssemblyInfo.cs#L84-L93

If we lived in a world where `mscorlib.dll` has `InternalsVisibleTo`
for `Mono.Android`, we can remove some System.Reflection that gets
called on startup.

We need to be able to call these methods directly:

* `System.Diagnostics.Debugger.Mono_UnhandledException`
* `AppDomain.CurrentDomain.DoUnhandledException`

The only other change is that some files need:

    using LogLevel = Android.Runtime.LogLevel;

There is an `internal` `System.LogLevel` that we need to disambiguate.

NOTE: this won't fully work until the change in Mono lands.

~~ Results ~~

I tested the Xamarin.Forms integration project, using a Debug build on
a HAXM x86 emulator on Windows.

The reason I looked into this, is I initially saw a log message like:

    12-03 14:28:11.969 27129 27129 I monodroid-timing: Runtime.register: registered type 'Android.Runtime.UncaughtExceptionHandler, Mono.Android'
    12-03 14:28:11.969 27129 27129 I monodroid-timing: Runtime.register: end time; elapsed: 0s:79::609300

After the change, it is more like:

    12-04 09:13:32.944  9758  9758 I monodroid-timing: Runtime.register: registered type 'Android.Runtime.UncaughtExceptionHandler, Mono.Android'
    12-04 09:13:32.944  9758  9758 I monodroid-timing: Runtime.register: end time; elapsed: 0s:73::727800

However, if I look at the total `Runtime.init` time:

    Before:
    12-03 14:27:48.494 26903 26903 I monodroid-timing: Runtime.init: end, total time; elapsed: 0s:601::443900
    12-03 14:27:54.356 26963 26963 I monodroid-timing: Runtime.init: end, total time; elapsed: 0s:587::495400
    12-03 14:28:00.263 27021 27021 I monodroid-timing: Runtime.init: end, total time; elapsed: 0s:586::147100
    12-03 14:28:06.135 27074 27074 I monodroid-timing: Runtime.init: end, total time; elapsed: 0s:593::639100
    12-03 14:28:11.988 27129 27129 I monodroid-timing: Runtime.init: end, total time; elapsed: 0s:571::194900
    After:
    12-04 09:13:15.386  9587  9587 I monodroid-timing: Runtime.init: end, total time; elapsed: 0s:584::909700
    12-04 09:13:21.179  9644  9644 I monodroid-timing: Runtime.init: end, total time; elapsed: 0s:506::64600
    12-04 09:13:27.148  9699  9699 I monodroid-timing: Runtime.init: end, total time; elapsed: 0s:560::98500
    12-04 09:13:32.963  9758  9758 I monodroid-timing: Runtime.init: end, total time; elapsed: 0s:504::939400
    12-04 09:13:38.887  9814  9814 I monodroid-timing: Runtime.init: end, total time; elapsed: 0s:531::234100

And then the total activity time:

    Before:
    12-03 14:27:51.450  1876  1898 I ActivityManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +3s727ms
    12-03 14:27:57.310  1876  1898 I ActivityManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +3s723ms
    12-03 14:28:03.216  1876  1898 I ActivityManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +3s703ms
    12-03 14:28:09.054  1876  1898 I ActivityManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +3s679ms
    12-03 14:28:14.953  1876  1898 I ActivityManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +3s711ms
    After:
    12-04 09:13:18.248  1876  1898 I ActivityManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +3s608ms
    12-04 09:13:24.087  1876  1898 I ActivityManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +3s570ms
    12-04 09:13:29.997  1876  1898 I ActivityManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +3s566ms
    12-04 09:13:35.805  1876  1898 I ActivityManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +3s498ms
    12-04 09:13:41.670  1876  1898 I ActivityManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +3s475ms

It seems like this might be saving us as much as ~250ms to the total
startup on a HAXM emulator in Debug mode?
jonathanpeppers added a commit to jonathanpeppers/mono that referenced this pull request Dec 4, 2019
Context: dotnet/android#3991

In Xamarin.Android, we have a bit of System.Reflection usage on
startup:

https://github.com/xamarin/xamarin-android/blob/bbbe2ed36e6eeb7cce0905dcbfdaeaa30754070f/src/Mono.Android/Android.Runtime/UncaughtExceptionHandler.cs#L47-L67

These methods are in `mscorlib.dll` and `internal`. If we had
`[assembly: InternalsVisibleTo ("Mono.Android")]` we could avoid the
System.Reflection.

This is already done for `Xamarin.iOS`, `Xamarin.Mac`, etc. so
hopefully it's OK to add one more?

We could then, just call these methods directly:

* `System.Diagnostics.Debugger.Mono_UnhandledException`
* `AppDomain.CurrentDomain.DoUnhandledException`

The results are possibly a 100-250ms improvement to startup:

    Before:
    12-03 14:27:51.450  1876  1898 I ActivityManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +3s727ms
    12-03 14:27:57.310  1876  1898 I ActivityManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +3s723ms
    12-03 14:28:03.216  1876  1898 I ActivityManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +3s703ms
    12-03 14:28:09.054  1876  1898 I ActivityManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +3s679ms
    12-03 14:28:14.953  1876  1898 I ActivityManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +3s711ms
    After:
    12-04 09:13:18.248  1876  1898 I ActivityManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +3s608ms
    12-04 09:13:24.087  1876  1898 I ActivityManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +3s570ms
    12-04 09:13:29.997  1876  1898 I ActivityManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +3s566ms
    12-04 09:13:35.805  1876  1898 I ActivityManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +3s498ms
    12-04 09:13:41.670  1876  1898 I ActivityManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +3s475ms

This was the Xamarin.Forms integration project in xamarin-android.
Running a `Debug` build on a HAXM x86 emulator on Windows.

https://github.com/xamarin/xamarin-android/tree/master/tests/Xamarin.Forms-Performance-Integration
akoeplinger pushed a commit to mono/mono that referenced this pull request Dec 4, 2019
* [corlib] add InternalsVisibleTo for Mono.Android

Context: dotnet/android#3991

In Xamarin.Android, we have a bit of System.Reflection usage on
startup:

https://github.com/xamarin/xamarin-android/blob/bbbe2ed36e6eeb7cce0905dcbfdaeaa30754070f/src/Mono.Android/Android.Runtime/UncaughtExceptionHandler.cs#L47-L67

These methods are in `mscorlib.dll` and `internal`. If we had
`[assembly: InternalsVisibleTo ("Mono.Android")]` we could avoid the
System.Reflection.

This is already done for `Xamarin.iOS`, `Xamarin.Mac`, etc. so
hopefully it's OK to add one more?

We could then, just call these methods directly:

* `System.Diagnostics.Debugger.Mono_UnhandledException`
* `AppDomain.CurrentDomain.DoUnhandledException`

The results are possibly a 100-250ms improvement to startup:

    Before:
    12-03 14:27:51.450  1876  1898 I ActivityManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +3s727ms
    12-03 14:27:57.310  1876  1898 I ActivityManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +3s723ms
    12-03 14:28:03.216  1876  1898 I ActivityManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +3s703ms
    12-03 14:28:09.054  1876  1898 I ActivityManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +3s679ms
    12-03 14:28:14.953  1876  1898 I ActivityManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +3s711ms
    After:
    12-04 09:13:18.248  1876  1898 I ActivityManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +3s608ms
    12-04 09:13:24.087  1876  1898 I ActivityManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +3s570ms
    12-04 09:13:29.997  1876  1898 I ActivityManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +3s566ms
    12-04 09:13:35.805  1876  1898 I ActivityManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +3s498ms
    12-04 09:13:41.670  1876  1898 I ActivityManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +3s475ms

This was the Xamarin.Forms integration project in xamarin-android.
Running a `Debug` build on a HAXM x86 emulator on Windows.

https://github.com/xamarin/xamarin-android/tree/master/tests/Xamarin.Forms-Performance-Integration

* Bump API snapshot submodule
monojenkins pushed a commit to monojenkins/mono that referenced this pull request Dec 4, 2019
Context: dotnet/android#3991

In Xamarin.Android, we have a bit of System.Reflection usage on
startup:

https://github.com/xamarin/xamarin-android/blob/bbbe2ed36e6eeb7cce0905dcbfdaeaa30754070f/src/Mono.Android/Android.Runtime/UncaughtExceptionHandler.cs#L47-L67

These methods are in `mscorlib.dll` and `internal`. If we had
`[assembly: InternalsVisibleTo ("Mono.Android")]` we could avoid the
System.Reflection.

This is already done for `Xamarin.iOS`, `Xamarin.Mac`, etc. so
hopefully it's OK to add one more?

We could then, just call these methods directly:

* `System.Diagnostics.Debugger.Mono_UnhandledException`
* `AppDomain.CurrentDomain.DoUnhandledException`

The results are possibly a 100-250ms improvement to startup:

    Before:
    12-03 14:27:51.450  1876  1898 I ActivityManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +3s727ms
    12-03 14:27:57.310  1876  1898 I ActivityManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +3s723ms
    12-03 14:28:03.216  1876  1898 I ActivityManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +3s703ms
    12-03 14:28:09.054  1876  1898 I ActivityManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +3s679ms
    12-03 14:28:14.953  1876  1898 I ActivityManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +3s711ms
    After:
    12-04 09:13:18.248  1876  1898 I ActivityManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +3s608ms
    12-04 09:13:24.087  1876  1898 I ActivityManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +3s570ms
    12-04 09:13:29.997  1876  1898 I ActivityManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +3s566ms
    12-04 09:13:35.805  1876  1898 I ActivityManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +3s498ms
    12-04 09:13:41.670  1876  1898 I ActivityManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +3s475ms

This was the Xamarin.Forms integration project in xamarin-android.
Running a `Debug` build on a HAXM x86 emulator on Windows.

https://github.com/xamarin/xamarin-android/tree/master/tests/Xamarin.Forms-Performance-Integration
akoeplinger pushed a commit to mono/mono that referenced this pull request Dec 4, 2019
* [corlib] add InternalsVisibleTo for Mono.Android

Context: dotnet/android#3991

In Xamarin.Android, we have a bit of System.Reflection usage on
startup:

https://github.com/xamarin/xamarin-android/blob/bbbe2ed36e6eeb7cce0905dcbfdaeaa30754070f/src/Mono.Android/Android.Runtime/UncaughtExceptionHandler.cs#L47-L67

These methods are in `mscorlib.dll` and `internal`. If we had
`[assembly: InternalsVisibleTo ("Mono.Android")]` we could avoid the
System.Reflection.

This is already done for `Xamarin.iOS`, `Xamarin.Mac`, etc. so
hopefully it's OK to add one more?

We could then, just call these methods directly:

* `System.Diagnostics.Debugger.Mono_UnhandledException`
* `AppDomain.CurrentDomain.DoUnhandledException`

The results are possibly a 100-250ms improvement to startup:

    Before:
    12-03 14:27:51.450  1876  1898 I ActivityManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +3s727ms
    12-03 14:27:57.310  1876  1898 I ActivityManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +3s723ms
    12-03 14:28:03.216  1876  1898 I ActivityManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +3s703ms
    12-03 14:28:09.054  1876  1898 I ActivityManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +3s679ms
    12-03 14:28:14.953  1876  1898 I ActivityManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +3s711ms
    After:
    12-04 09:13:18.248  1876  1898 I ActivityManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +3s608ms
    12-04 09:13:24.087  1876  1898 I ActivityManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +3s570ms
    12-04 09:13:29.997  1876  1898 I ActivityManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +3s566ms
    12-04 09:13:35.805  1876  1898 I ActivityManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +3s498ms
    12-04 09:13:41.670  1876  1898 I ActivityManager: Displayed Xamarin.Forms_Performance_Integration/xamarin.forms.performance.integration.MainActivity: +3s475ms

This was the Xamarin.Forms integration project in xamarin-android.
Running a `Debug` build on a HAXM x86 emulator on Windows.

https://github.com/xamarin/xamarin-android/tree/master/tests/Xamarin.Forms-Performance-Integration

* Bump API snapshot submodule
@jonpryor
Copy link
Contributor

jonpryor commented Dec 6, 2019

If we lived in a world where mscorlib.dll has InternalsVisibleTo for Mono.Android,

We may be able to live in such a world in the short-term (d16-6) timeframe.

I'm dubious about us continuing to live in such a world in the .NET 5 timeframe. It's entirely plausible that in .NET 5 "everybody" will be using the same assemblies, and those assemblies might not have InternalsVisibleTo.

It's thus potentially dubious.

Furthermore, the Reflection usage only occurs when there's an actual unhandled exception, when UncaughtExceptionHandler.UncaughtException() is executed. We're speeding up what should be a rare occurrence (probably followed quickly by process death).

@jonathanpeppers
Copy link
Member Author

We're speeding up what should be a rare occurrence (probably followed quickly by process death).

I am now wondering how I saw a speedup. I ran a script to time this, but I wonder if I could have messed something up? The change landed in mono-2019-12, so I can retest when we are on it.

in .NET 5 "everybody" will be using the same assemblies

This came up here: mono/mono#18040 (comment)

My thought was a build-time error would be better than a runtime error (and only on unhandled exception!). It could slightly help us migrate to .NET 5.

@jonathanpeppers
Copy link
Member Author

Closing in favor of: #4302

@github-actions github-actions bot locked and limited conversation to collaborators Jan 28, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants