了解F#内存消耗

时间:2015-05-05 13:42:27

标签: memory f#

我最近一直在玩F#并在下面写下这个小片段,它只是创建了一些随机的3d矢量,将它们放入一个列表中,将每个矢量映射到它的长度并总结所有这些值

运行程序(作为Release Build .exe,而不是交互式),二进制文件在这种特殊情况下消耗(10 mio向量)大约550 MB RAM。一个Vec3对象应该占12个字节(或16个假设进行一些对齐)。即使您使用32字节进行粗略计算以解决一些簿记开销(每个对象的字节数* 10 mio)/ 1024/1024),您仍然比实际消耗量减少200 MB。天真地,我假设最终每个单位有10个mio * 4个字节,因为Vec3对象被映射掉了。

我的猜测到目前为止:要么我在某处保留一份(或几份)我的清单副本,我不知道这一点,或者某些中间结果从未被垃圾收集过?我无法想象从System.Object继承会带来如此多的开销。 有人能指出我正确的方向吗?

TIA

type Vec3(x: single, y: single, z:single) = 

    let mag = sqrt(x*x + y*y + z*z)

    member self.Magnitude = mag

    override self.ToString() = sprintf "[%f %f %f]" x y z

let how_much = 10000000

let mutable rng = System.Random()

let sw = new System.Diagnostics.Stopwatch()
sw.Start()

let random_vec_iter len =

    let mutable result = []

    for x = 1 to len do
        let mutable accum = []

        for i = 1 to 3 do
            accum <- single(rng.NextDouble())::accum
        result <- Vec3(accum.[0], accum.[1], accum.[2])::result
    result

sum_len_func = List.reduce (fun x y -> x+y)
let map_to_mag_func = List.map (fun (x:Vec3) -> x.Magnitude)

[<EntryPoint>]
let main argv = 
    printfn "Hello, World"
    let res = sum_len_func (map_to_mag_func (random_vec_iter(how_much)))
    printfn "doing stuff with %i items took %i, result is %f" how_much     (sw.ElapsedMilliseconds) res
    System.Console.ReadKey() |> ignore
    0 // return an integer exit code

1 个答案:

答案 0 :(得分:3)

首先,你的vec是ref类型而不是值类型(不是struct)。所以你在12字节(12 + 16)的顶部按住一个指针。然后列表是单链接列表,因此.net引用的另外16个字节。然后,您的List.map将创建一个中间列表。