Understanding memory allocation in Sdf_Path: discrepancy between class size and pool element size

I have a technical question regarding the code structure of an API and am seeking assistance from someone with in-depth knowledge of it. During a porting process using clang, I examined the code related to ‘Sdf_Path’ and observed that the ‘Sdf_PathNode’ (edit) class has a size of 16 bytes, which includes 8 bytes for an ‘intrusive_ptr’ (+4 bytes for the reference count and 4 bytes for other variables).

However, I noticed that all elements in the pool are defined as follows:

SDF_INSTANTIATE_POOL(Sdf_PathPrimTag, Sdf_SizeofPrimPathNode, /*regionBits=*/8);
SDF_INSTANTIATE_POOL(Sdf_PathPropTag, Sdf_SizeofPropPathNode, /*regionBits=*/8);

where ‘Sdf_SizeofPrimPathNode’ and ‘Sdf_SizeofPropPathNode’ are each calculated as:

// These are validated below.
static constexpr size_t Sdf_SizeofPrimPathNode = sizeof(void *) * 3;
static constexpr size_t Sdf_SizeofPropPathNode = sizeof(void *) * 3;

This results in 24 bytes on an x86 architecture. I am puzzled because it seems like I might be missing something regarding the utilization of the last 8 bytes. They don’t appear to be allocated for ‘Sdf_PathNode’ storage, and I couldn’t find any code indicating their use. The ‘*3’ multiplier in the ‘Sdf_SizeofPrimPathNode’ calculation particularly stands out as an unexplained or “magic” number. While the rest of the code is logical, well-documented, and structured, this detail seems inconsistent.

I would appreciate any insights or explanations regarding this aspect.


Hey Mark,

sizeof(SdfPath) is 8 – it has two members:

Sdf_PathPrimNodeHandle _primPart;
Sdf_PathPropNodeHandle _propPart;

Each of which is 4 bytes. These are “pool handles” which are “indexes” into the path node pools. They’re really just “small pointers” to keep sizeof(SdfPath) == 8.

The sizeof(Sdf_PrimPathNode) and sizeof(Sdf_PrimPropertyPathNode) are 24 each as you found. The _primPart and _propPart handles in SdfPath each potentially refer to one of these nodes, which are allocated in the path node pools.

An Sdf_PrimPathNode is 24 bytes because its base class Sdf_PathNode has these members:

    const Sdf_PathNodeConstRefPtr _parent;
    mutable std::atomic<uint32_t> _refCount;
    const uint16_t _elementCount;
    const NodeType _nodeType;
    const uint8_t _nodeFlags;

Which are 8 + 4 + 2 + 1 + 1 = 16 bytes, and then Sdf_PrimPathNode itself adds:

TfToken _name;

Which is an additional 8 bytes, bringing the total to 24. Maybe that token name member is the missing piece?

Hope that helps and lmk if you have more questions!


I’m grateful for your response. Firstly, I need to apologize. I just noticed a mistake in my initial question. I was actually referring to the size of Sdf_PathNode, not Sdf_Path, which, fortunately, you seemed to understand correctly. We’re on the same page about the Sdf_PathNode being 16 bytes. However, I completely overlooked the TfToken in Sdf_PrimPathNode. That was the element I was missing. Since my focus was primarily on the creation of the absolute path root, I hadn’t looked for additional members in subclasses. Thank you for your help!