F#: Why is Array.createZero so fast?

2019-01-28 11:07发布

问题:

I have this code:

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

I tested it and had these results:

0ms
200ms

How does Array.zeroCreate create array so fast and it's guaranteed that all it's elements have default value? In other languages I know there are no such possibilities (as far as I know). In other languages I know only about fast initialization of array which elements are not guaranteed to have default value, because they can be initialized in memory where some garbage lies.

Thanks!

回答1:

So we can just go and look up the source:

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

and

    [<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

so from this we can see that Create does some more work - so it is slower.

We can go deeper and find the underlying function:

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

this basically just executes the CIL newarr instruction.

This instruction could quite conceiveably be executed by calling calloc with an appropriate size, which would be incredibly fast.