Skip to content

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

@xlxs4

Description

@xlxs4

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions