Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Base.summarysize(::Symbol) returns zero #55549

Open
xlxs4 opened this issue Aug 21, 2024 · 0 comments
Open

Base.summarysize(::Symbol) returns zero #55549

xlxs4 opened this issue Aug 21, 2024 · 0 comments

Comments

@xlxs4
Copy link
Contributor

xlxs4 commented Aug 21, 2024

From a conversation at Slack w/ @tecosaur:

julia> Base.summarysize(:hello)
0

summarysize 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

julia/src/julia.h

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;

julia/src/symbol.c

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")
13

instead, which to me feels more close to what's actually going on behind the hood.

@xlxs4 xlxs4 changed the title Base.summarysize(::Symbol) returns zero Base.summarysize(::Symbol) returns zero Aug 21, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant