IGNORE's per-TU static akerr_last_ignored costs 37 KB of TLS per translation unit #37
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Measured while bumping
akbasicfrom libakerror 2.0.1 to the currentmain(ee38eed).include/akerror.tmpl.h:219defines the ignored-error snapshot as a file-scope object in the public header:Because it is
static, every translation unit that includesakerror.hgets its own copy, and because it isAKERR_THREAD_LOCALevery copy is thread-local storage.akerr_ErrorContextis large —AKERR_MAX_ERROR_FNAME_LENGTHdefaults to 4096 and there are two such fields — so each copy is substantial.Measured
sizeof(akerr_ErrorContext)= 37,296 bytes at default options.akbasic's
basicdriver, default configuration, Debug:__akerr_last_ignored, anexternpointer)main0x15a020= 1,417,248 bytesreadelf -sW build/basicshows 38akerr_last_ignoredsymbols; 38 x 37,296 = 1,417,248 exactly. The entire TLS segment is this one variable, duplicated once per TU, and it scales with translation-unit count rather than with anything about the program.That is ~1.35 MiB of per-thread storage in a project that recently spent a release cutting its interpreter's static footprint from 10.75 MiB to 2.40 MiB, and it would be paid again by every thread a host game spawns.
Second, smaller symptom
A
staticobject defined in a header and unused in most TUs warns. The same build emits 84 instances of:one per TU that includes the header without using
IGNORE. Consumers building with-Werrorcannot includeakerror.h.Why it is written this way
I think the snapshot is deliberate and correct:
4fe7571("Release ignored error contexts") madeIGNOREcopy the context so the pool slot can be released, which fixes a real leak. The issue is only where the copy lives — one per TU rather than one per thread.Suggested direction
Declare it
extern AKERR_THREAD_LOCAL akerr_ErrorContext akerr_last_ignored;in the header and define it once insrc/error.c, which restores one copy per thread and silences the warning. If it must stay in the header,AKERR_MAYBE_UNUSED/__attribute__((unused))fixes the warning but not the footprint.Tests that would cover it
akerror.hand never callsIGNORE, under-Wall -Wextra -Werror.tests/negative/is the existing shape for a compile that must behave a particular way.Beginning work on issue #37: I will move the ignored-error TLS snapshot to a single library definition, add focused coverage for multi-TU storage and warning behavior, then open a signed pull request.
Work complete. Moved akerr_last_ignored from the public header’s static TLS definition to an extern declaration with one definition in src/error.c. Added a two-translation-unit regression test compiled with -Wall -Wextra -Werror; err_ignore and err_ignore_multitu both pass. Pull request: #40