1f9317f7bSKadir Cetinkaya //===--- MemoryTree.h - A special tree for components and sizes -*- C++ -*-===// 2f9317f7bSKadir Cetinkaya // 3f9317f7bSKadir Cetinkaya // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4f9317f7bSKadir Cetinkaya // See https://llvm.org/LICENSE.txt for license information. 5f9317f7bSKadir Cetinkaya // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6f9317f7bSKadir Cetinkaya // 7f9317f7bSKadir Cetinkaya //===----------------------------------------------------------------------===// 8f9317f7bSKadir Cetinkaya 9*48e6ff9aSHaojian Wu #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_SUPPORT_MEMORYTREE_H 10*48e6ff9aSHaojian Wu #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_SUPPORT_MEMORYTREE_H 11f9317f7bSKadir Cetinkaya 12c9d2876dSKadir Cetinkaya #include "Trace.h" 13f9317f7bSKadir Cetinkaya #include "llvm/ADT/DenseMap.h" 14f9317f7bSKadir Cetinkaya #include "llvm/ADT/StringRef.h" 15f9317f7bSKadir Cetinkaya #include "llvm/Support/Allocator.h" 16f9317f7bSKadir Cetinkaya #include <cstddef> 17f9317f7bSKadir Cetinkaya #include <string> 18f9317f7bSKadir Cetinkaya #include <vector> 19f9317f7bSKadir Cetinkaya 20f9317f7bSKadir Cetinkaya namespace clang { 21f9317f7bSKadir Cetinkaya namespace clangd { 22f9317f7bSKadir Cetinkaya 23f9317f7bSKadir Cetinkaya /// A tree that can be used to represent memory usage of nested components while 24f9317f7bSKadir Cetinkaya /// preserving the hierarchy. 25f9317f7bSKadir Cetinkaya /// Edges have associated names. An edge that might not be interesting to all 26f9317f7bSKadir Cetinkaya /// traversers or costly to copy (e.g. file names) can be marked as "detail". 27f9317f7bSKadir Cetinkaya /// Tree construction allows chosing between a detailed and brief mode, in brief 28f9317f7bSKadir Cetinkaya /// mode all "detail" edges are ignored and tree is constructed without any 29f9317f7bSKadir Cetinkaya /// string copies. 30f9317f7bSKadir Cetinkaya struct MemoryTree { 31f9317f7bSKadir Cetinkaya public: 32f9317f7bSKadir Cetinkaya /// If Alloc is nullptr, tree is in brief mode and will ignore detail edges. 33f9317f7bSKadir Cetinkaya MemoryTree(llvm::BumpPtrAllocator *DetailAlloc = nullptr) DetailAllocMemoryTree34f9317f7bSKadir Cetinkaya : DetailAlloc(DetailAlloc) {} 35f9317f7bSKadir Cetinkaya 36f9317f7bSKadir Cetinkaya /// No copy of the \p Name. 37f9317f7bSKadir Cetinkaya /// Note that returned pointers are invalidated with subsequent calls to 38f9317f7bSKadir Cetinkaya /// child/detail. childMemoryTree39f9317f7bSKadir Cetinkaya MemoryTree &child(llvm::StringLiteral Name) { return createChild(Name); } 40f9317f7bSKadir Cetinkaya 41f9317f7bSKadir Cetinkaya MemoryTree(const MemoryTree &) = delete; 42f9317f7bSKadir Cetinkaya MemoryTree &operator=(const MemoryTree &) = delete; 43f9317f7bSKadir Cetinkaya 44f9317f7bSKadir Cetinkaya MemoryTree(MemoryTree &&) = default; 45f9317f7bSKadir Cetinkaya MemoryTree &operator=(MemoryTree &&) = default; 46f9317f7bSKadir Cetinkaya 47f9317f7bSKadir Cetinkaya /// Makes a copy of the \p Name in detailed mode, returns current node 48f9317f7bSKadir Cetinkaya /// otherwise. 49f9317f7bSKadir Cetinkaya /// Note that returned pointers are invalidated with subsequent calls to 50f9317f7bSKadir Cetinkaya /// child/detail. detailMemoryTree51f9317f7bSKadir Cetinkaya MemoryTree &detail(llvm::StringRef Name) { 52f9317f7bSKadir Cetinkaya return DetailAlloc ? createChild(Name.copy(*DetailAlloc)) : *this; 53f9317f7bSKadir Cetinkaya } 54f9317f7bSKadir Cetinkaya 55f9317f7bSKadir Cetinkaya /// Increases size of current node by \p Increment. addUsageMemoryTree56f9317f7bSKadir Cetinkaya void addUsage(size_t Increment) { Size += Increment; } 57f9317f7bSKadir Cetinkaya 58f9317f7bSKadir Cetinkaya /// Returns edges to direct children of this node. 59f9317f7bSKadir Cetinkaya const llvm::DenseMap<llvm::StringRef, MemoryTree> &children() const; 60f9317f7bSKadir Cetinkaya 61f9317f7bSKadir Cetinkaya /// Returns total number of bytes used by this sub-tree. Performs a traversal. 62f9317f7bSKadir Cetinkaya size_t total() const; 63f9317f7bSKadir Cetinkaya 64f9317f7bSKadir Cetinkaya /// Returns total number of bytes used by this node only. selfMemoryTree65f9317f7bSKadir Cetinkaya size_t self() const { return Size; } 66f9317f7bSKadir Cetinkaya 67f9317f7bSKadir Cetinkaya private: 68f9317f7bSKadir Cetinkaya /// Adds a child with an edge labeled as \p Name. Multiple calls to this 69f9317f7bSKadir Cetinkaya /// function returns the same node. 70f9317f7bSKadir Cetinkaya MemoryTree &createChild(llvm::StringRef Name); 71f9317f7bSKadir Cetinkaya 72f9317f7bSKadir Cetinkaya /// Allocator to use for detailed edge names. 73f9317f7bSKadir Cetinkaya llvm::BumpPtrAllocator *DetailAlloc = nullptr; 74f9317f7bSKadir Cetinkaya 75f9317f7bSKadir Cetinkaya /// Bytes owned by this component specifically. 76f9317f7bSKadir Cetinkaya size_t Size = 0; 77f9317f7bSKadir Cetinkaya 78f9317f7bSKadir Cetinkaya /// Edges from current node to its children. Keys are the labels for edges. 79f9317f7bSKadir Cetinkaya llvm::DenseMap<llvm::StringRef, MemoryTree> Children; 80f9317f7bSKadir Cetinkaya }; 81f9317f7bSKadir Cetinkaya 82c9d2876dSKadir Cetinkaya /// Records total memory usage of each node under \p Out. Labels are edges on 83c9d2876dSKadir Cetinkaya /// the path joined with ".", starting with \p RootName. 84c9d2876dSKadir Cetinkaya void record(const MemoryTree &MT, std::string RootName, 85c9d2876dSKadir Cetinkaya const trace::Metric &Out); 86c9d2876dSKadir Cetinkaya 87f9317f7bSKadir Cetinkaya } // namespace clangd 88f9317f7bSKadir Cetinkaya } // namespace clang 89f9317f7bSKadir Cetinkaya 90f9317f7bSKadir Cetinkaya #endif 91