xref: /llvm-project/clang-tools-extra/clangd/support/MemoryTree.h (revision 48e6ff9ad3eb1971de6d7ba12e31754781aff675)
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