@@ -60,9 +60,21 @@ Index64 countActiveTiles(const TreeT& tree, bool threaded = true);
6060
6161
6262// / @brief Return the total amount of memory in bytes occupied by this tree.
63+ // / @details This method returns the total in-core memory usage which can be
64+ // / different to the maximum possible memory usage for trees which have not
65+ // / been fully deserialized (via delay-loading). Thus, this is the current
66+ // / true memory consumption.
6367template <typename TreeT>
6468Index64 memUsage (const TreeT& tree, bool threaded = true );
6569
70+
71+ // / @brief Return the deserialized memory usage of this tree. This is not
72+ // / necessarily equal to the current memory usage (returned by tools::memUsage)
73+ // / if delay-loading is enabled. See File::open.
74+ template <typename TreeT>
75+ Index64 memUsageIfLoaded (const TreeT& tree, bool threaded = true );
76+
77+
6678// / @brief Return the minimum and maximum active values in this tree.
6779// / @note Returns zeroVal<ValueType> for empty trees.
6880template <typename TreeT>
@@ -287,21 +299,22 @@ struct MemUsageOp
287299 using RootT = typename TreeType::RootNodeType;
288300 using LeafT = typename TreeType::LeafNodeType;
289301
290- MemUsageOp () = default ;
291- MemUsageOp (const MemUsageOp&, tbb::split) { }
302+ MemUsageOp (const bool inCoreOnly) : mInCoreOnly (inCoreOnly) {}
303+ MemUsageOp (const MemUsageOp& other) : mCount (0 ), mInCoreOnly (other.mInCoreOnly ) {}
304+ MemUsageOp (const MemUsageOp& other, tbb::split) : MemUsageOp(other) {}
292305
293306 // accumulate size of the root node in bytes
294307 bool operator ()(const RootT& root, size_t )
295308 {
296- count += sizeof (root);
309+ mCount += sizeof (root);
297310 return true ;
298311 }
299312
300313 // accumulate size of all child nodes in bytes
301314 template <typename NodeT>
302315 bool operator ()(const NodeT& node, size_t )
303316 {
304- count += NodeT::NUM_VALUES * sizeof (typename NodeT::UnionType) +
317+ mCount += NodeT::NUM_VALUES * sizeof (typename NodeT::UnionType) +
305318 node.getChildMask ().memUsage () + node.getValueMask ().memUsage () +
306319 sizeof (Coord);
307320 return true ;
@@ -310,16 +323,18 @@ struct MemUsageOp
310323 // accumulate size of leaf node in bytes
311324 bool operator ()(const LeafT& leaf, size_t )
312325 {
313- count += leaf.memUsage ();
326+ if (mInCoreOnly ) mCount += leaf.memUsage ();
327+ else mCount += leaf.memUsageIfLoaded ();
314328 return false ;
315329 }
316330
317331 void join (const MemUsageOp& other)
318332 {
319- count += other.count ;
333+ mCount += other.mCount ;
320334 }
321335
322- openvdb::Index64 count{0 };
336+ openvdb::Index64 mCount {0 };
337+ const bool mInCoreOnly ;
323338}; // struct MemUsageOp
324339
325340// / @brief A DynamicNodeManager operator to find the minimum and maximum active values in this tree.
@@ -477,10 +492,24 @@ Index64 countActiveTiles(const TreeT& tree, bool threaded)
477492template <typename TreeT>
478493Index64 memUsage (const TreeT& tree, bool threaded)
479494{
480- count_internal::MemUsageOp<TreeT> op;
495+ count_internal::MemUsageOp<TreeT> op (true );
496+ tree::DynamicNodeManager<const TreeT> nodeManager (tree);
497+ nodeManager.reduceTopDown (op, threaded);
498+ return op.mCount + sizeof (tree);
499+ }
500+
501+ template <typename TreeT>
502+ Index64 memUsageIfLoaded (const TreeT& tree, bool threaded)
503+ {
504+ // / @note For numeric (non-point) grids this really doesn't need to
505+ // / traverse the tree and could instead be computed from the node counts.
506+ // / We do so anyway as it ties this method into the tree data structure
507+ // / which makes sure that changes to the tree/nodes are reflected/kept in
508+ // / sync here.
509+ count_internal::MemUsageOp<TreeT> op (false );
481510 tree::DynamicNodeManager<const TreeT> nodeManager (tree);
482511 nodeManager.reduceTopDown (op, threaded);
483- return op.count + sizeof (tree);
512+ return op.mCount + sizeof (tree);
484513}
485514
486515template <typename TreeT>
0 commit comments