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