Page MenuHomePhabricator

[AST] Reduce the size of TemplateArgumentLocInfo.

Authored by hokein on Sep 3 2020, 2:58 AM.



allocate the underlying data of Template kind separately, this would reduce AST memory usage

  • TemplateArgumentLocInfo 24 => 8 bytes
  • TemplateARgumentLoc 48 => 32 bytes
  • DynTypeNode 56 => 40 bytes

Diff Detail

Event Timeline

hokein created this revision.Sep 3 2020, 2:58 AM
Herald added a project: Restricted Project. · View Herald Transcript
Herald added a subscriber: martong. · View Herald Transcript
hokein requested review of this revision.Sep 3 2020, 2:58 AM

Nit on the commit message: I think this is TemplateArgumentLoc 48 -> 32 bytes, and DynTypedNode 56 -> 40 bytes.


Can you use PointerUnion<Expr*, T*, TypeSourceInfo*>, and save even more of the boilerplate?


this is a no-op, and thus not worth stashing a pointer to Ctx for!

It also doesn't delete T, and it's probably best to do that even if it's (currently) a no-op


If you're going to destroy T in the destructor, then you can't have trivial copies, as the second one is pointing at deallocated memory.
(Well, apart from the fact that deallocation does nothing).

So I think we probably either want:

  • allocation on ASTContext, trivial copies, no deallocation
  • allocation on heap, copies reallocate
  • allocation on heap using shared_ptr
  • copies disallowed (but I think we rely on them being available)

this is not "heap allocation" in the usual sense - allocating in the context's slab allocator is cheaper but can't be deallocated.

Not sure how this compares to simply new T instead.

If not, then as with delete, I'd prefer new (Ctx) T (I think it's correct without as long as T is trivial, but less obvious)

hokein updated this revision to Diff 290187.Sep 6 2020, 11:53 PM
hokein marked 2 inline comments as done.

address review comments:

  • use PointerUnion
  • keep the TemplateArgumentLocInfo trivial, allocate from allocator, no deallocation.
hokein edited the summary of this revision. (Show Details)Sep 6 2020, 11:56 PM
hokein edited the summary of this revision. (Show Details)
hokein added inline comments.Sep 7 2020, 12:00 AM

chose the first one.

martong removed a subscriber: martong.Sep 7 2020, 12:56 AM

Looks good apart from a minor technical issue with the traits.

Would it be possible to compile some big file in LLVM (probably doesn't matter much which, Sema something?) and observe if there's a significant change in overall ASTContext size?


At first glance this is unsafe: you could have two different definitions of the same specialization in different files.

In fact it's OK, the default one can now never be instantiated, because Expr.h includes this file and so anyone that can see the definition can see this specialization.

But this is subtle/fragile: at least it needs to be spelled out explicitly in the comment.
I'd also suggest adding a static assert below the definition of Expr that it is compatible with this specialization (because it is sufficiently aligned).

(I can't think of a better alternative - use of PointerUnion is a win, partly *because* it validates the alignment)


the pattern here (use of Ctx for allocation although other variants don't) is unusual, maybe add a comment

hokein updated this revision to Diff 293029.Sep 20 2020, 1:47 PM
hokein marked an inline comment as done.

address review comments.

Would it be possible to compile some big file in LLVM (probably doesn't matter much which, Sema something?) and observe if there's a significant change in overall ASTContext size?

~3% saving (measuring the ASTContext::.getASTAllocatedMemory)

SemaDecl.cpp255.5 MB247.5MB
SemaExpr.cpp293.5 MB283.5MB

yes, exactly.

do you have a better idea on how the static_assert should look like? The way I can think of is to add a new flag in this specialization, and use static_assert(PointerLikeTypeTraits<clang::Expr *>::flag, "...").

rsmith added a subscriber: rsmith.Sep 20 2020, 3:08 PM
rsmith added inline comments.

This may be included from Expr.h right now, but really doesn't seem like the right header to hold this specialization. Perhaps we should consider adding something like an AST/ForwardDecls.h, containing forward declarations and specializations such as this one, and include that from Expr.h and from here?


If you're going to add more uses of the name T, we should rename it to something more descriptive. Maybe TemplateTemplateArgLocInfo or something like that?


I think this is just about complex enough to be worth moving to the .cpp file.


This is redundant (here and below): get does this assert for you.

sammccall added inline comments.Sep 21 2020, 12:52 AM

I think this is it:

// PointerLikeTypeTraits is specialized so it can be used with a forward-decl of Expr.
// Verify that we got it right.
static_assert((1 << PointerLikeTypeTraits<Expr*>::NumLowBitsAvailable) == alignof(Expr), "PointerLikeTypeTraits<Expr*> assumes too much alignment");

(Or just % alignof(Expr) == 0 if you want a weaker condition)


I also had this thought but wasn't sure. @hokein maybe a trivial followup patch rather than inline here?

hokein updated this revision to Diff 293094.Sep 21 2020, 1:34 AM
hokein marked 2 inline comments as done.

address review comments.

hokein added inline comments.Sep 21 2020, 1:35 AM

Ah, thanks. alignof(Expr) is 8, I feel like comparing the Numbits directly seems more easy to understand.


that sounds good to me.

sammccall accepted this revision.Sep 21 2020, 2:46 AM

Forgot to mention, 3% memory saving is huge, way more than I expected (was mostly just hoping for no regression).
Nice work!


I'd extend this comment a bit to explain why: "This case is unusually large and also rare, so we store the payload out-of-line."

This revision is now accepted and ready to land.Sep 21 2020, 2:46 AM
This revision was landed with ongoing or failed builds.Sep 21 2020, 4:09 AM
This revision was automatically updated to reflect the committed changes.
hokein marked an inline comment as done.