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
20namespace clang {
21namespace 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.
30struct MemoryTree {
31public:
32 /// If Alloc is nullptr, tree is in brief mode and will ignore detail edges.
33 MemoryTree(llvm::BumpPtrAllocator *DetailAlloc = nullptr)
34 : DetailAlloc(DetailAlloc) {}
35
36 /// No copy of the \p Name.
37 /// Note that returned pointers are invalidated with subsequent calls to
38 /// child/detail.
39 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.
51 MemoryTree &detail(llvm::StringRef Name) {
52 return DetailAlloc ? createChild(Name: Name.copy(A&: *DetailAlloc)) : *this;
53 }
54
55 /// Increases size of current node by \p Increment.
56 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.
65 size_t self() const { return Size; }
66
67private:
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.
84void record(const MemoryTree &MT, std::string RootName,
85 const trace::Metric &Out);
86
87} // namespace clangd
88} // namespace clang
89
90#endif
91

source code of clang-tools-extra/clangd/support/MemoryTree.h