-
-
Notifications
You must be signed in to change notification settings - Fork 5.7k
Description
From a conversation at Slack w/ @tecosaur:
julia> Base.summarysize(:hello)
0summarysize is explicitly coded to return 0 for Symbols.
The docstring reads:
help?> Base.summarysize
Base.summarysize(obj; exclude=Union{...}, chargeall=Union{...}) -> Int
Compute the amount of memory, in bytes, used by all unique objects reachable from
the argument.Symbols are interned strings with a hash, and all subsequent references are a pointer to the interned value
Lines 140 to 148 in 86cba99
| // Symbols are interned strings (hash-consed) stored as an invasive binary tree. | |
| // The string data is nul-terminated and hangs off the end of the struct. | |
| typedef struct _jl_sym_t { | |
| JL_DATA_TYPE | |
| _Atomic(struct _jl_sym_t*) left; | |
| _Atomic(struct _jl_sym_t*) right; | |
| uintptr_t hash; // precomputed hash value | |
| // JL_ATTRIBUTE_ALIGN_PTRSIZE(char name[]); | |
| } jl_sym_t; |
Lines 35 to 49 in 86cba99
| static jl_sym_t *mk_symbol(const char *str, size_t len) JL_NOTSAFEPOINT | |
| { | |
| jl_sym_t *sym; | |
| size_t nb = symbol_nbytes(len); | |
| jl_taggedvalue_t *tag = (jl_taggedvalue_t*)jl_gc_perm_alloc(nb, 0, sizeof(void*), 0); | |
| sym = (jl_sym_t*)jl_valueof(tag); | |
| // set to old marked so that we won't look at it in the GC or write barrier. | |
| jl_set_typetagof(sym, jl_symbol_tag, GC_OLD_MARKED); | |
| jl_atomic_store_relaxed(&sym->left, NULL); | |
| jl_atomic_store_relaxed(&sym->right, NULL); | |
| sym->hash = hash_symbol(str, len); | |
| memcpy(jl_symbol_name(sym), str, len); | |
| jl_symbol_name(sym)[len] = 0; | |
| return sym; | |
| } |
So why would we have summarysize report 0? Shouldn't summarysize(x) == sizeof(x) for x::Symbol?
That method instance was originally added in 8322d79, with a comment reading # these three cases override the exception that would be thrown by Core.sizeof. Looking at the current source code for summarysize, I can't find any sizeof calls that would throw if that definition wasn't there. Is this a historical artifact? I've tried to find the commit where the comment was removed (e.g., it's still there in 34236e7) but git log -c -S and co. failed me.
Removing the mi doesn't seem to break anything, and we get
julia> sizeof(:hello)
5
julia> Base.summarysize(:hello)
5
julia> sizeof("hello")
5
julia> Base.summarysize("hello")
13instead, which to me feels more close to what's actually going on behind the hood.