0

我想看看以下 2 个简单的递归函数是否能像 C# 版本一样执行,所以我使用 ILSPY 将它们反编译成 C#。

    let rec findPivot i =
        if i = 0 then -1
        else
            if myArray.[i] > myArray.[i-1] then i - 1
            else findPivot (i - 1)

    let rec findTarget value i =
        if (myArray.[i] > value) then i
        else findTarget value (i - 1)

得到:

internal static int findPivot@11(int[] myArray, int i)
{
    while (i != 0)
    {
        if (myArray[i] > myArray[i - 1])
        {
            return i - 1;
        }
        int[] arg_22_0 = myArray; // useless
        i--;
        myArray = arg_22_0; // useless
    }
    return -1;
}

internal static int findTarget@17(int[] myArray, int value, int i)
{
    while (myArray[i] <= value)
    {
        int[] arg_16_0 = myArray; // useless
        int arg_14_0 = value; // useless
        i--;
        value = arg_14_0; // useless
        myArray = arg_16_0; // useless
    }
    return i;
}

我很惊讶 F# 编译会生成如此混乱的代码。尽管它可能不会影响性能(JIT 可能会进一步优化)。当代码在系统中更加复杂和关键时,我仍然有点担心性能。

关于编译器为何发出此类代码的任何评论?

4

1 回答 1

2

我已经调查过了,似乎 IL 被误解为新本地的声明。请记住,F# 编译器生成的 IL 并不总是与 C# 编译器匹配。似乎 F# 编译器将重新分配参数,无论它们是否在循环中发生了变异。请注意,我们没有声明本地变量,因此所有内容都被推入堆栈。

.method public static 
    int32 findTarget (
        int32 'value',
        int32 i
    ) cil managed 
{
    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = (
        01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00
    )
    // Method begins at RVA 0x2084
    // Code size 27 (0x1b)
    .maxstack 8

    // loop start
        IL_0000: nop
        IL_0001: call int32[] Program::get_myArray()
        IL_0006: ldarg.1
        IL_0007: ldelem.any [mscorlib]System.Int32
        IL_000c: ldarg.0
        IL_000d: ble.s IL_0011

        IL_000f: ldarg.1
        IL_0010: ret

        IL_0011: ldarg.0
        IL_0012: ldarg.1
        IL_0013: ldc.i4.1
        IL_0014: sub
        IL_0015: starg.s i
        IL_0017: starg.s 'value'
        IL_0019: br.s IL_0000
    // end loop
} // end of method Program::findTarget
于 2013-05-06T23:29:55.420 回答