Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Julia 朱莉娅:为什么GC速度慢,内存中有大量可变结构_Julia - Fatal编程技术网

Julia 朱莉娅:为什么GC速度慢,内存中有大量可变结构

Julia 朱莉娅:为什么GC速度慢,内存中有大量可变结构,julia,Julia,与非可变结构相比,当大量可变结构加载到内存中时,为什么垃圾收集会慢得多?在这两种情况下,对象树的大小应该相同 julia> struct Foo a::Float64 b::Float64 c::Float64 end julia> mutable struct Bar a::Float64 b::Float64 c::Float64

与非可变结构相比,当大量可变结构加载到内存中时,为什么垃圾收集会慢得多?在这两种情况下,对象树的大小应该相同

julia> struct Foo
           a::Float64
           b::Float64
           c::Float64
       end

julia> mutable struct Bar
           a::Float64
           b::Float64
           c::Float64
       end

julia> @time dat1 = [Foo(0.0, 0.0, 0.0) for i in 1:1e9];
  9.706709 seconds (371.88 k allocations: 22.371 GiB, 0.14% gc time)

julia> @time GC.gc(true)
  0.104186 seconds, 100.00% gc time

julia> @time GC.gc(true)
  0.124675 seconds, 100.00% gc time

julia> @time dat2 = [Bar(0.0, 0.0, 0.0) for i in 1:1e9];
 71.870870 seconds (1.00 G allocations: 37.256 GiB, 73.88% gc time)

julia> @time GC.gc(true)
 47.695473 seconds, 100.00% gc time

julia> @time GC.gc(true)
 41.809898 seconds, 100.00% gc time

不可变结构可以直接存储在数组中。对于可变结构,这永远不会发生。在您的例子中,
Foo
对象都直接存储在
dat1
中,因此在创建Arary之后,实际上只有一个(尽管非常大)的分配可以访问

dat2
的情况下,每个
Bar
对象都将有自己的内存分配给它,数组将包含对这些对象的引用。因此,使用
dat2
,您最终会得到1G+1可到达的分配

您还可以使用
Base.sizeof
来查看这一点:

julia> sizeof(dat1)
24000000000

julia> sizeof(dat2)
8000000000
您将看到
dat1
是3倍大,因为每个数组条目直接包含3个
Float64
s,而
dat2
中的条目只占用每个指针的空间

附带说明:对于这类测试,最好使用
基准测试工具。@btime
而不是内置的
@time
。因为它消除了结果中的编译开销,并且多次运行代码以获得更具代表性的结果:

@btime dat1 = [Foo(0.0, 0.0, 0.0) for i in 1:1e6]
  2.237 ms (2 allocations: 22.89 MiB)

@btime dat2 = [Bar(0.0, 0.0, 0.0) for i in 1:1e6]
  6.878 ms (1000002 allocations: 38.15 MiB)

如上所述,这对于调试分配特别有用。对于
dat1
我们得到2个分配(一个用于
Array
实例本身,一个用于数组存储其数据的内存块),而对于
dat2
我们每个元素有一个额外的分配。

知道为什么创建
dat1
有300k个分配吗?这是汇编吗?@OscarSmith可能是的。除了简单的玩弄之外,您还需要使用
BenchmarkTools
中的
btime
,它将负责从基准测试结果中删除编译,并将多次运行代码以获得更好的估计。