//===--- MemoryTree.h - A special tree for components and sizes -*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_SUPPORT_MEMORYTREE_H_ #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_SUPPORT_MEMORYTREE_H_ #include "Trace.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/StringSaver.h" #include #include #include namespace clang { namespace clangd { /// A tree that can be used to represent memory usage of nested components while /// preserving the hierarchy. /// Edges have associated names. An edge that might not be interesting to all /// traversers or costly to copy (e.g. file names) can be marked as "detail". /// Tree construction allows chosing between a detailed and brief mode, in brief /// mode all "detail" edges are ignored and tree is constructed without any /// string copies. struct MemoryTree { public: /// If Alloc is nullptr, tree is in brief mode and will ignore detail edges. MemoryTree(llvm::BumpPtrAllocator *DetailAlloc = nullptr) : DetailAlloc(DetailAlloc) {} /// No copy of the \p Name. /// Note that returned pointers are invalidated with subsequent calls to /// child/detail. MemoryTree &child(llvm::StringLiteral Name) { return createChild(Name); } MemoryTree(const MemoryTree &) = delete; MemoryTree &operator=(const MemoryTree &) = delete; MemoryTree(MemoryTree &&) = default; MemoryTree &operator=(MemoryTree &&) = default; /// Makes a copy of the \p Name in detailed mode, returns current node /// otherwise. /// Note that returned pointers are invalidated with subsequent calls to /// child/detail. MemoryTree &detail(llvm::StringRef Name) { return DetailAlloc ? createChild(Name.copy(*DetailAlloc)) : *this; } /// Increases size of current node by \p Increment. void addUsage(size_t Increment) { Size += Increment; } /// Returns edges to direct children of this node. const llvm::DenseMap &children() const; /// Returns total number of bytes used by this sub-tree. Performs a traversal. size_t total() const; /// Returns total number of bytes used by this node only. size_t self() const { return Size; } private: /// Adds a child with an edge labeled as \p Name. Multiple calls to this /// function returns the same node. MemoryTree &createChild(llvm::StringRef Name); /// Allocator to use for detailed edge names. llvm::BumpPtrAllocator *DetailAlloc = nullptr; /// Bytes owned by this component specifically. size_t Size = 0; /// Edges from current node to its children. Keys are the labels for edges. llvm::DenseMap Children; }; /// Records total memory usage of each node under \p Out. Labels are edges on /// the path joined with ".", starting with \p RootName. void record(const MemoryTree &MT, std::string RootName, const trace::Metric &Out); } // namespace clangd } // namespace clang #endif