内容简介:翻译自:https://stackoverflow.com/questions/10452011/f-for-loop-optimization
代码示例:
let foo1 (arr : int[]) = for i = 0 to arr.Length-1 do arr.[i] <- i let foo2 (arr : int[]) = for i in [0..arr.Length-1] do arr.[i] <- i
我认为这个功能应该相互对应(在性能方面).但如果我们查看IL列表,我们会看到:
第一个函数,15行,没有动态分配,没有try运算符,没有虚拟调用:
IL_0000: nop IL_0001: ldc.i4.0 IL_0002: stloc.0 IL_0003: br.s IL_0011 // loop start (head: IL_0011) IL_0005: ldarg.0 IL_0006: ldloc.0 IL_0007: ldloc.0 IL_0008: stelem.any [mscorlib]System.Int32 IL_000d: ldloc.0 IL_000e: ldc.i4.1 IL_000f: add IL_0010: stloc.0 IL_0011: ldloc.0 IL_0012: ldarg.0 IL_0013: ldlen IL_0014: conv.i4 IL_0015: blt.s IL_0005 // end loop IL_0017: ret
第二个 – 几乎100行,大量的分配/解除分配,虚拟函数的调用,大量的try / Dispose:
IL_0000: nop IL_0001: ldc.i4.0 IL_0002: ldc.i4.1 IL_0003: ldarg.0 IL_0004: ldlen IL_0005: conv.i4 IL_0006: ldc.i4.1 IL_0007: sub IL_0008: call class [mscorlib]System.Collections.Generic.IEnumerable`1<int32> [FSharp.Core]Microsoft.FSharp.Core.Operators/OperatorIntrinsics::RangeInt32(int32, int32, int32) IL_000d: call class [mscorlib]System.Collections.Generic.IEnumerable`1<!!0> [FSharp.Core]Microsoft.FSharp.Core.Operators::CreateSequence<int32>(class [mscorlib]System.Collections.Generic.IEnumerable`1<!!0>) IL_0012: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<!!0> [FSharp.Core]Microsoft.FSharp.Collections.SeqModule::ToList<int32>(class [mscorlib]System.Collections.Generic.IEnumerable`1<!!0>) IL_0017: stloc.0 IL_0018: ldloc.0 IL_0019: unbox.any class [mscorlib]System.Collections.Generic.IEnumerable`1<int32> IL_001e: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerator`1<!0> class [mscorlib]System.Collections.Generic.IEnumerable`1<int32>::GetEnumerator() IL_0023: stloc.1 .try { // loop start (head: IL_0024) IL_0024: ldloc.1 IL_0025: callvirt instance bool [mscorlib]System.Collections.IEnumerator::MoveNext() IL_002a: brfalse.s IL_003e IL_002c: ldloc.1 IL_002d: callvirt instance !0 class [mscorlib]System.Collections.Generic.IEnumerator`1<int32>::get_Current() IL_0032: stloc.3 IL_0033: ldarg.0 IL_0034: ldloc.3 IL_0035: ldloc.3 IL_0036: stelem.any [mscorlib]System.Int32 IL_003b: nop IL_003c: br.s IL_0024 // end loop IL_003e: ldnull IL_003f: stloc.2 IL_0040: leave.s IL_005b } // end .try finally { IL_0042: ldloc.1 IL_0043: isinst [mscorlib]System.IDisposable IL_0048: stloc.s 4 IL_004a: ldloc.s 4 IL_004c: brfalse.s IL_0058 IL_004e: ldloc.s 4 IL_0050: callvirt instance void [mscorlib]System.IDisposable::Dispose() IL_0055: ldnull IL_0056: pop IL_0057: endfinally IL_0058: ldnull IL_0059: pop IL_005a: endfinally } // end handler IL_005b: ldloc.2 IL_005c: pop IL_005d: ret
我的问题是为什么F#编译器使用如此复杂的foo2代码?为什么它使用IEnumerable来实现这么简单的循环?
在第二个示例中,如果使用范围表达式,它将转换为正常for循环:
let foo2 (arr : int[]) = for i in 0..arr.Length-1 do arr.[i] <- i
并变得等同于foo1.
我引用 Section 6.3.12 Range Expressions in F# language specs :
A sequence iteration expression of the form for var in expr1 .. expr2 do expr3 done is sometimes elaborated as a simple for loop-expression (§6.5.7).
但是,你的第二个例子更像是:
let foo2 (arr : int[]) = let xs = [0..arr.Length-1] (* A new list is created *) for i in xs do arr.[i] <- i
您已明确创建新列表的位置.
翻译自:https://stackoverflow.com/questions/10452011/f-for-loop-optimization
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Building Social Web Applications
Gavin Bell / O'Reilly Media / 2009-10-1 / USD 34.99
Building a social web application that attracts and retains regular visitors, and gets them to interact, isn't easy to do. This book walks you through the tough questions you'll face if you're to crea......一起来看看 《Building Social Web Applications》 这本书的介绍吧!