单例数组的魔力从何而来?
Where does the magic of singleton arrays come from?
Vector{Missing}
和 Vector{Int}
之间的以下差异让我感到惊讶(以积极的方式):
julia> @btime fill(20, 10^7);
15.980 ms (2 allocations: 76.29 MiB)
julia> @btime fill(missing, 10^7);
20.603 ns (1 allocation: 80 bytes)
julia> Base.summarysize(fill(20, 10^7))
80000040
julia> Base.summarysize(fill(missing, 10^7))
40
julia> typeof(fill(20, 10^7))
Vector{Int64} (alias for Array{Int64, 1})
julia> typeof(fill(missing, 10^7))
Vector{Missing} (alias for Array{Missing, 1})
鉴于 fill(missing, n)
不会产生像 FillArray
这样的一些优化结构,这种对单例的优化是如何实现的?我猜它会以某种方式自动地从单例的大小为零这一事实中消失,但是如何呢?
我尝试阅读 array.c and julia.h,但无法真正理解其中的细节。也许真正的问题是 运行时系统如何处理单例...?
基本答案是,对于 a = Array(T)
Julia 总是分配 sizeof(T)*length(a)+40
字节。由于 sizeof(Missing) == 0
,这意味着它不会分配任何与长度相关的字节。
索引发生在line 569 of array.c
,相关行是
jl_value_t *r = undefref_check((jl_datatype_t*)eltype, jl_new_bits(eltype, &((char*)a->data)[i * a->elsize]))
当数组大小为零时,a->data[i * a->elsize]
指的是a->data
的开头。然而,它的内容是完全不相关的:当 eltype
有零时 jl_datatype_size
,jl_new_bits
ignores the data pointer 而不是 returns 来自的 instance
字段eltype
,这是单例对象。
Vector{Missing}
和 Vector{Int}
之间的以下差异让我感到惊讶(以积极的方式):
julia> @btime fill(20, 10^7);
15.980 ms (2 allocations: 76.29 MiB)
julia> @btime fill(missing, 10^7);
20.603 ns (1 allocation: 80 bytes)
julia> Base.summarysize(fill(20, 10^7))
80000040
julia> Base.summarysize(fill(missing, 10^7))
40
julia> typeof(fill(20, 10^7))
Vector{Int64} (alias for Array{Int64, 1})
julia> typeof(fill(missing, 10^7))
Vector{Missing} (alias for Array{Missing, 1})
鉴于 fill(missing, n)
不会产生像 FillArray
这样的一些优化结构,这种对单例的优化是如何实现的?我猜它会以某种方式自动地从单例的大小为零这一事实中消失,但是如何呢?
我尝试阅读 array.c and julia.h,但无法真正理解其中的细节。也许真正的问题是 运行时系统如何处理单例...?
基本答案是,对于 a = Array(T)
Julia 总是分配 sizeof(T)*length(a)+40
字节。由于 sizeof(Missing) == 0
,这意味着它不会分配任何与长度相关的字节。
索引发生在line 569 of array.c
,相关行是
jl_value_t *r = undefref_check((jl_datatype_t*)eltype, jl_new_bits(eltype, &((char*)a->data)[i * a->elsize]))
当数组大小为零时,a->data[i * a->elsize]
指的是a->data
的开头。然而,它的内容是完全不相关的:当 eltype
有零时 jl_datatype_size
,jl_new_bits
ignores the data pointer 而不是 returns 来自的 instance
字段eltype
,这是单例对象。