我最近一直在玩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
答案 0 :(得分:3)
首先,你的vec是ref类型而不是值类型(不是struct)。所以你在12字节(12 + 16)的顶部按住一个指针。然后列表是单链接列表,因此.net引用的另外16个字节。然后,您的List.map将创建一个中间列表。