内容简介:翻译自: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
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
大数据系统构建
Nathan Marz、James Warren / 马延辉、向磊、魏东琦 / 机械工业出版社 / 2017-1 / 79.00
随着社交网络、网络分析和智能型电子商务的兴起,传统的数据库系统显然已无法满足海量数据的管理需求。 作为一种新的处理模式,大数据系统应运而生,它使用多台机器并行工作,能够对海量数据进行存储、处理、分析,进而帮助用户从中提取对优化流程、实现高增长率的有用信息,做更为精准有效的决策。 但不可忽略的是,它也引入了大多数开发者并不熟悉的、困扰传统架构的复杂性问题。 本书将教你充分利用集群硬件优势的La......一起来看看 《大数据系统构建》 这本书的介绍吧!