Za pomocą atrybutu System.Runtime.CompilerServices.MethodImplAttribute
można podać wskazówki kompilatorowi JIT dotyczące sposobu obsługi dekorowanej metody. W szczególności opcja MethodImplOptions.AggressiveInlining
instruuje kompilator, aby w razie potrzeby zainicjował metodę, której dotyczy problem. Niestety kompilator F # wydaje się po prostu ignorować ten atrybut podczas generowania IL.Zastosowanie MethodImplOptions.AggressiveInlining do funkcji F #
Przykład: Następujący kod C#
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int Inc(int x) => x + 1;
jest tłumaczony
.method public hidebysig static int32 Inc(int32 x) cil managed aggressiveinlining
{
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldc.i4.1
IL_0002: add
IL_0003: ret
}
Uwaga "aggressiveinlining" Flag.
F # Kod ten jednak
[<MethodImpl(MethodImplOptions.AggressiveInlining)>]
let inc x = x + 1
staje
.method public static int32 inc(int32 x) cil managed
{
.maxstack 8
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldc.i4.1
IL_0003: add
IL_0004: ret
}
Nie "aggressiveinlining". Próbowałem również zastosować ten atrybut do statycznych i niestatycznych metod właściwych klas (type ...
), ale wynik jest taki sam.
Jeśli jednak mogę zastosować go do niestandardowych indekser, tak jak
type Dummy =
member self.Item
with [<MethodImpl(MethodImplOptions.AggressiveInlining)>] get x = x + 1
otrzymany IL jest
.method public hidebysig specialname instance int32 get_Item(int32 x) cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.MethodImplAttribute::.ctor(valuetype [mscorlib]System.Runtime.CompilerServices.MethodImplOptions) = (01 00 00 01 00 00 00 00)
.maxstack 8
IL_0000: nop
IL_0001: ldarg.1
IL_0002: ldc.i4.1
IL_0003: add
IL_0004: ret
}
... choć nie jestem pewien, czy to jest równoznaczne z " agresywna flaga generowana przez kompilator C#.
Czy to pożądane zachowanie/oczekiwane? Czy jest to błąd w kompilatorze F #?
(Uwaga: Jestem świadomy F # inline
hasła, ale to działa tylko dla F # klientów mojej bibliotece, a nie C# konsumentów.)
AFAIK ten atrybut jest używany przez JIT: er, aby wskazać, że metoda powinna być inline. Jeśli tak, powinieneś sprawdzić wygenerowany kod maszyny.Uwaga; nie jest tak proste, jak przeglądanie demontażu w .NET, jak w przypadku debuggera z JIT: er jest znacznie mniej agresywny. – FuleSnabel
Awww, rozumiem co masz na myśli. Wydaje się, że brakuje go w meta danych IL. Pozwól mi to sprawdzić później. – FuleSnabel
Wygląda na to, że respektowane są tylko 'PreserveSig',' Synchronized' oraz 'NoInlining' - patrz' ComputeMethodImplAttribs' w [IlxGen.fs] (https://github.com/Microsoft/visualfsharp/blob/master/src/fsharp /IlxGen.fs) – kvb