F#:为什么Array.createZero这么快?

Sav*_*xey 3 arrays f# initialization array-initialization

我有这个代码:

let timer = new System.Diagnostics.Stopwatch()
timer.Start()
Array.zeroCreate<int> 100000000

timer.Stop()
printfn "%ims" timer.ElapsedMilliseconds

timer.Reset()
timer.Start()
Array.create 100000000 0

timer.Stop()
printfn "%ims" timer.ElapsedMilliseconds
Run Code Online (Sandbox Code Playgroud)

我测试了它并得到了这些结果:

0ms
200ms
Run Code Online (Sandbox Code Playgroud)

如何Array.zeroCreate快速创建数组并确保其所有元素都具有默认值?在其他语言中,我知道没有这样的可能性(据我所知).在其他语言中,我只知道数组的快速初始化,哪些元素不能保证具有默认值,因为它们可以在存储器中初始化,其中存在一些垃圾.

谢谢!

Joh*_*mer 6

所以我们可以去查找源代码:

    [<CompiledName("ZeroCreate")>]
    let zeroCreate count =
        if count < 0 then invalidArg "count" (SR.GetString(SR.inputMustBeNonNegative))
        Microsoft.FSharp.Primitives.Basics.Array.zeroCreateUnchecked count
Run Code Online (Sandbox Code Playgroud)

    [<CompiledName("Create")>]
    let create (count:int) (x:'T) =
        if count < 0 then invalidArg "count" (SR.GetString(SR.inputMustBeNonNegative))
        let array = (Microsoft.FSharp.Primitives.Basics.Array.zeroCreateUnchecked count : 'T[])
        for i = 0 to Operators.Checked.(-) count 1 do // use checked arithmetic here to satisfy FxCop
            array.[i] <- x
        array
Run Code Online (Sandbox Code Playgroud)

所以我们可以看到它Create做了一些更多的工作 - 所以它更慢.

我们可以更深入地找到基本功能:

// The input parameter should be checked by callers if necessary
let inline zeroCreateUnchecked (count:int) =
    (# "newarr !0" type ('T) count : 'T array #)
Run Code Online (Sandbox Code Playgroud)

这基本上只是执行CIL newarr指令.

通过calloc使用适当的大小调用可以非常可靠地执行该指令,这将非常快.

  • 值得一提的是为什么`calloc`(及其等价物)可以这么快:http://stackoverflow.com/questions/2688466/why-mallocmemset-is-slower-than-calloc (5认同)