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!
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.