-
Notifications
You must be signed in to change notification settings - Fork 545
NativeAOT TODO list #9784
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Alternate "MVP 1.1" typemap idea, for posterity: instead of a
The linker step would populate (1), which might be faster because At runtime, consult (2) first, and if a type mapping doesn't exist, use (1) to lookup the Questions:
|
There must be a way to use a android/src/Microsoft.Android.Sdk.ILLink/TypeMappingStep.cs Lines 70 to 83 in 70bd636
|
|
I'm currently exploring this direction for the type map: https://gist.github.com/simonrozsival/8b3f2294d7fa1cf84ca32e8145984c98
What do you think? |
@simonrozsival brought up a point that the
|
I don't think I expressed myself correctly. If we generate IL that builds the I was trying to say that we cannot serialize the raw numeric values of We can of course create an array of RTH, but it will need to be initialized at startup: static readonly RuntimeTypeHandle[] s_handles = [ typeof(X).TypeHandle, typeof(Y).TypeHandle ];
// is compiled to IL like this:
.method private hidebysig specialname rtspecialname static
void .cctor () cil managed
{
// Method begins at RVA 0x2058
// Code size 56 (0x38)
.maxstack 8
IL_0000: ldc.i4.2
IL_0001: newarr [System.Runtime]System.RuntimeTypeHandle
IL_0006: dup
IL_0007: ldc.i4.0
IL_0008: ldtoken X
IL_000d: call class [System.Runtime]System.Type [System.Runtime]System.Type::GetTypeFromHandle(valuetype [System.Runtime]System.RuntimeTypeHandle)
IL_0012: callvirt instance valuetype [System.Runtime]System.RuntimeTypeHandle [System.Runtime]System.Type::get_TypeHandle()
IL_0017: stelem [System.Runtime]System.RuntimeTypeHandle
IL_001c: dup
IL_001d: ldc.i4.1
IL_001e: ldtoken Y
IL_0023: call class [System.Runtime]System.Type [System.Runtime]System.Type::GetTypeFromHandle(valuetype [System.Runtime]System.RuntimeTypeHandle)
IL_0028: callvirt instance valuetype [System.Runtime]System.RuntimeTypeHandle [System.Runtime]System.Type::get_TypeHandle()
IL_002d: stelem [System.Runtime]System.RuntimeTypeHandle
IL_0032: stsfld valuetype [System.Runtime]System.RuntimeTypeHandle[] X::s_handles
IL_0037: ret
} // end of method X::.cctor |
ILC can interpret some static constructors at compile time and produce preinitialized data in the executable image. It would not work for the Dictionary but it can probably work for a simple array... (or can be tweaked to work if it doesn't at the moment) |
For zero-alloc string->Type dictionary known at build-time, we can generate a lookup method using stack-based Benchmark string->Typeusing System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Diagnosers;
using BenchmarkDotNet.Running;
BenchmarkRunner.Run<LookupBenchmark>();
[MemoryDiagnoser] // Memory diagnostics enabled
public class LookupBenchmark
{
private readonly string[] existingKeys = [nameof(Int32), nameof(Object), nameof(String), nameof(Boolean)];
private readonly string[] missingKeys = ["key999", "unknown", "hello", "test123"];
[Benchmark]
public void Dictionary_PositiveLookups()
{
Dictionary<string, Type> dataDictionary = new()
{
[nameof(Int32)] = typeof(int),
[nameof(Object)] = typeof(object),
[nameof(String)] = typeof(string),
[nameof(Boolean)] = typeof(bool)
};
foreach (var key in existingKeys)
{
var result = dataDictionary[key];
}
}
[Benchmark]
public void Dictionary_NegativeLookups()
{
Dictionary<string, Type> dataDictionary = new()
{
[nameof(Int32)] = typeof(int),
[nameof(Object)] = typeof(object),
[nameof(String)] = typeof(string),
[nameof(Boolean)] = typeof(bool)
};
foreach (var key in missingKeys)
{
_ = dataDictionary.TryGetValue(key, out _);
}
}
[Benchmark]
public void Static_PositiveLookups()
{
foreach (var key in existingKeys)
{
_ = TryFind(key, out _);
}
static bool TryFind(ReadOnlySpan<char> key, out Type value)
{
if (key.Length == 0)
{
value = default;
return false;
}
ReadOnlySpan<char> keysConcat = "Int32ObjectStringBoolean";
ReadOnlySpan<int> keyOffsets = [0, 5, 11, 17];
ReadOnlySpan<int> keyLengths = [5, 6, 6, 7];
ReadOnlySpan<Type> values = [typeof(System.Int32), typeof(System.Object), typeof(System.String), typeof(System.Boolean)];
int searchStart = 0;
while (true)
{
int foundOffset = searchStart + keysConcat[searchStart..].IndexOf(key);
if (foundOffset < 0)
{
value = default;
return false;
}
int keyIndex = keyOffsets.IndexOf(foundOffset);
if (key.Length != keyLengths[keyIndex])
{
if (keyIndex + 1 >= keyOffsets.Length)
{
value = default;
return false;
}
searchStart = keyOffsets[keyIndex + 1];
continue;
}
value = values[keyIndex];
return true;
}
}
}
[Benchmark]
public void Static_NegativeLookups()
{
foreach (var key in missingKeys)
{
_ = TryFind(key, out _);
}
static bool TryFind(ReadOnlySpan<char> key, out Type value)
{
if (key.Length == 0)
{
value = default;
return false;
}
ReadOnlySpan<char> keysConcat = "Int32ObjectStringBoolean";
ReadOnlySpan<int> keyOffsets = [0, 5, 11, 17];
ReadOnlySpan<int> keyLengths = [5, 6, 6, 7];
ReadOnlySpan<Type> values = [typeof(System.Int32), typeof(System.Object), typeof(System.String), typeof(System.Boolean)];
int searchStart = 0;
while (true)
{
int foundOffset = searchStart + keysConcat[searchStart..].IndexOf(key);
if (foundOffset < 0)
{
value = default;
return false;
}
int keyIndex = keyOffsets.IndexOf(foundOffset);
if (key.Length != keyLengths[keyIndex])
{
if (keyIndex + 1 >= keyOffsets.Length)
{
value = default;
return false;
}
searchStart = keyOffsets[keyIndex + 1];
continue;
}
value = values[keyIndex];
return true;
}
}
}
}
With just array of 4 items, we start to see the difference. Roslyn source generator: https://github.com/am11/GeneratedLookup |
@am11 we have an implementation that doesn't use |
What do we need to do for NativeAOT?
To investigate next:
dotnet publish
doesn't work,dotnet build
does workdotnet new maui
template stopped working in main at some pointList of TODOs:
dotnet new android && dotnet publish -p:PublishAot=true
Microsoft.Android.Runtime.NativeAOT.dll
#9760dotnet new maui
runs: [WIP] turn NativeAOT sample into a .NET MAUI app #9747debug.mono.log
, to disablelref/gref
loggingmonodroid_log()
for NativeAOT$(PublishAotUsingRuntimePack)=true
, and see what xamarin/xamarin-macios does$(PublishAotUsingRuntimePack)=true
#9815SynchronizationContext
#9883libc++_shared.so
JNINativeWrapper.CreateDelegate (...)
?The text was updated successfully, but these errors were encountered: