Skip to content

Commit

Permalink
some improvements to summarysize, fixes #32881 (#32886)
Browse files Browse the repository at this point in the history
- 0-field mutable structs take 1 word
- take uniqueness into account for Strings
- include union selector bytes for Arrays
  • Loading branch information
JeffBezanson authored Aug 15, 2019
1 parent 4c0049c commit 1f564ce
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 5 deletions.
2 changes: 1 addition & 1 deletion base/atomics.jl
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,7 @@ inttype(::Type{Float32}) = Int32
inttype(::Type{Float64}) = Int64


gc_alignment(::Type{T}) where {T} = ccall(:jl_alignment, Cint, (Csize_t,), sizeof(T))
import ..Base.gc_alignment

# All atomic operations have acquire and/or release semantics, depending on
# whether the load or store values. Most of the time, this is what one wants
Expand Down
3 changes: 3 additions & 0 deletions base/reflection.jl
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,9 @@ function datatype_alignment(dt::DataType)
return Int(alignment & 0x1FF)
end

gc_alignment(sz::Integer) = Int(ccall(:jl_alignment, Cint, (Csize_t,), sz))
gc_alignment(T::Type) = gc_alignment(Core.sizeof(T))

"""
Base.datatype_haspadding(dt::DataType) -> Bool
Expand Down
24 changes: 20 additions & 4 deletions base/summarysize.jl
Original file line number Diff line number Diff line change
Expand Up @@ -74,14 +74,25 @@ end
end
if isa(obj, UnionAll) || isa(obj, Union)
# black-list of items that don't have a Core.sizeof
return 2 * sizeof(Int)
sz = 2 * sizeof(Int)
else
sz = Core.sizeof(obj)
end
return Core.sizeof(obj)
if sz == 0
# 0-field mutable structs are not unique
return gc_alignment(0)
end
return sz
end

(::SummarySize)(obj::Symbol) = 0
(::SummarySize)(obj::SummarySize) = 0
(::SummarySize)(obj::String) = Core.sizeof(Int) + Core.sizeof(obj)

function (ss::SummarySize)(obj::String)
key = ccall(:jl_value_ptr, Ptr{Cvoid}, (Any,), obj)
haskey(ss.seen, key) ? (return 0) : (ss.seen[key] = true)
return Core.sizeof(Int) + Core.sizeof(obj)
end

function (ss::SummarySize)(obj::DataType)
key = pointer_from_objref(obj)
Expand All @@ -108,7 +119,12 @@ function (ss::SummarySize)(obj::Array)
datakey = unsafe_convert(Ptr{Cvoid}, obj)
if !haskey(ss.seen, datakey)
ss.seen[datakey] = true
size += Core.sizeof(obj)
dsize = Core.sizeof(obj)
if isbitsunion(eltype(obj))
# add 1 union selector byte for each element
dsize += length(obj)
end
size += dsize
if !isbitstype(eltype(obj)) && !isempty(obj)
push!(ss.frontier_x, obj)
push!(ss.frontier_i, 1)
Expand Down
9 changes: 9 additions & 0 deletions test/misc.jl
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,15 @@ let A = zeros(1000), B = reshape(A, (1,1000))
@test summarysize(A) > sizeof(A)
end

# issue #32881
mutable struct S32881; end
let s = "abc"
@test summarysize([s,s]) < summarysize(["abc","xyz"])
end
@test summarysize(Vector{Union{Nothing,Missing}}(undef, 16)) < summarysize(Vector{Union{Nothing,Missing}}(undef, 32))
@test summarysize(Vector{Nothing}(undef, 16)) == summarysize(Vector{Nothing}(undef, 32))
@test summarysize(S32881()) == sizeof(Int)

# issue #13021
let ex = try
Main.x13021 = 0
Expand Down

0 comments on commit 1f564ce

Please sign in to comment.