forked from OSchip/llvm-project
[clangd] Add $/memoryUsage LSP extension
Performs a detailed profiling of clangd lsp server and conveys the result to the client as a json object. It is of the form: { "_self": 0, "_total": 8, "child1": { "_self": 4, "_total": 4, } "child2": { "_self": 2, "_total": 4, "child_deep": { "_self": 2, "_total": 2, } } } Differential Revision: https://reviews.llvm.org/D89277
This commit is contained in:
parent
0b7b446a40
commit
d0f287464d
|
@ -36,8 +36,11 @@
|
|||
#include "llvm/Support/Path.h"
|
||||
#include "llvm/Support/SHA1.h"
|
||||
#include "llvm/Support/ScopedPrinter.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <chrono>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
|
@ -617,6 +620,7 @@ void ClangdLSPServer::onInitialize(const InitializeParams &Params,
|
|||
ExecuteCommandParams::CLANGD_APPLY_TWEAK}},
|
||||
}},
|
||||
{"typeHierarchyProvider", true},
|
||||
{"memoryUsageProvider", true}, // clangd extension.
|
||||
}}}};
|
||||
if (Opts.Encoding)
|
||||
Result["offsetEncoding"] = *Opts.Encoding;
|
||||
|
@ -1383,6 +1387,14 @@ void ClangdLSPServer::onSemanticTokensDelta(
|
|||
});
|
||||
}
|
||||
|
||||
void ClangdLSPServer::onMemoryUsage(const NoParams &,
|
||||
Callback<MemoryTree> Reply) {
|
||||
llvm::BumpPtrAllocator DetailAlloc;
|
||||
MemoryTree MT(&DetailAlloc);
|
||||
profile(MT);
|
||||
Reply(std::move(MT));
|
||||
}
|
||||
|
||||
ClangdLSPServer::ClangdLSPServer(class Transport &Transp,
|
||||
const ThreadsafeFS &TFS,
|
||||
const ClangdLSPServer::Options &Opts)
|
||||
|
@ -1425,6 +1437,7 @@ ClangdLSPServer::ClangdLSPServer(class Transport &Transp,
|
|||
MsgHandler->bind("textDocument/documentLink", &ClangdLSPServer::onDocumentLink);
|
||||
MsgHandler->bind("textDocument/semanticTokens/full", &ClangdLSPServer::onSemanticTokens);
|
||||
MsgHandler->bind("textDocument/semanticTokens/full/delta", &ClangdLSPServer::onSemanticTokensDelta);
|
||||
MsgHandler->bind("$/memoryUsage", &ClangdLSPServer::onMemoryUsage);
|
||||
if (Opts.FoldingRanges)
|
||||
MsgHandler->bind("textDocument/foldingRange", &ClangdLSPServer::onFoldingRange);
|
||||
// clang-format on
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "llvm/ADT/StringSet.h"
|
||||
#include "llvm/Support/JSON.h"
|
||||
#include <chrono>
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
|
||||
namespace clang {
|
||||
|
@ -141,6 +142,9 @@ private:
|
|||
void onSemanticTokens(const SemanticTokensParams &, Callback<SemanticTokens>);
|
||||
void onSemanticTokensDelta(const SemanticTokensDeltaParams &,
|
||||
Callback<SemanticTokensOrDelta>);
|
||||
/// This is a clangd extension. Provides a json tree representing memory usage
|
||||
/// hierarchy.
|
||||
void onMemoryUsage(const NoParams &, Callback<MemoryTree>);
|
||||
|
||||
std::vector<Fix> getFixes(StringRef File, const clangd::Diagnostic &D);
|
||||
|
||||
|
|
|
@ -1300,5 +1300,17 @@ llvm::json::Value toJSON(const FoldingRange &Range) {
|
|||
return Result;
|
||||
}
|
||||
|
||||
llvm::json::Value toJSON(const MemoryTree &MT) {
|
||||
llvm::json::Object Out;
|
||||
int64_t Total = MT.self();
|
||||
Out["_self"] = Total;
|
||||
for (const auto &Entry : MT.children()) {
|
||||
auto Child = toJSON(Entry.getSecond());
|
||||
Total += *Child.getAsObject()->getInteger("_total");
|
||||
Out[Entry.first] = std::move(Child);
|
||||
}
|
||||
Out["_total"] = Total;
|
||||
return Out;
|
||||
}
|
||||
} // namespace clangd
|
||||
} // namespace clang
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
#include "URI.h"
|
||||
#include "index/SymbolID.h"
|
||||
#include "support/MemoryTree.h"
|
||||
#include "clang/Index/IndexSymbol.h"
|
||||
#include "llvm/ADT/Optional.h"
|
||||
#include "llvm/Support/JSON.h"
|
||||
|
@ -1576,6 +1577,27 @@ struct FoldingRange {
|
|||
};
|
||||
llvm::json::Value toJSON(const FoldingRange &Range);
|
||||
|
||||
/// Keys starting with an underscore(_) represent leaves, e.g. _total or _self
|
||||
/// for memory usage of whole subtree or only that specific node in bytes. All
|
||||
/// other keys represents children. An example:
|
||||
/// {
|
||||
/// "_self": 0,
|
||||
/// "_total": 8,
|
||||
/// "child1": {
|
||||
/// "_self": 4,
|
||||
/// "_total": 4,
|
||||
/// }
|
||||
/// "child2": {
|
||||
/// "_self": 2,
|
||||
/// "_total": 4,
|
||||
/// "child_deep": {
|
||||
/// "_self": 2,
|
||||
/// "_total": 2,
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
llvm::json::Value toJSON(const MemoryTree &MT);
|
||||
|
||||
} // namespace clangd
|
||||
} // namespace clang
|
||||
|
||||
|
|
|
@ -66,6 +66,7 @@
|
|||
# CHECK-NEXT: ]
|
||||
# CHECK-NEXT: },
|
||||
# CHECK-NEXT: "hoverProvider": true,
|
||||
# CHECK-NEXT: "memoryUsageProvider": true
|
||||
# CHECK-NEXT: "referencesProvider": true,
|
||||
# CHECK-NEXT: "renameProvider": true,
|
||||
# CHECK-NEXT: "selectionRangeProvider": true,
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
# RUN: clangd -lit-test < %s | FileCheck -strict-whitespace %s
|
||||
{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}}
|
||||
---
|
||||
{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///main.cpp","languageId":"cpp","version":1,"text":"void func() {}"}}}
|
||||
---
|
||||
{"jsonrpc":"2.0","id":1,"method":"$/memoryUsage","params":{}}
|
||||
# CHECK: "id": 1,
|
||||
# CHECK-NEXT: "jsonrpc": "2.0",
|
||||
# CHECK-NEXT: "result": {
|
||||
# CHECK-NEXT: "_self": {{[0-9]+}},
|
||||
# CHECK-NEXT: "_total": {{[0-9]+}},
|
||||
# CHECK-NEXT: "clangd_server": {
|
||||
# CHECK-NEXT: "_self": {{[0-9]+}},
|
||||
# CHECK-NEXT: "_total": {{[0-9]+}},
|
||||
# CHECK-NEXT: "dynamic_index": {
|
||||
# CHECK-NEXT: "_self": {{[0-9]+}},
|
||||
# CHECK-NEXT: "_total": {{[0-9]+}},
|
||||
# CHECK-NEXT: "main_file": {
|
||||
# CHECK-NEXT: "_self": {{[0-9]+}},
|
||||
# CHECK-NEXT: "_total": {{[0-9]+}},
|
||||
# CHECK-NEXT: "index": {
|
||||
# CHECK-NEXT: "_self": {{[0-9]+}},
|
||||
# CHECK-NEXT: "_total": {{[0-9]+}}
|
||||
# CHECK-NEXT: },
|
||||
# CHECK-NEXT: "symbols": {
|
||||
# CHECK-NEXT: "{{.*}}main.cpp": {
|
||||
# CHECK-NEXT: "_self": {{[0-9]+}},
|
||||
# CHECK-NEXT: "_total": {{[0-9]+}},
|
||||
# CHECK-NEXT: "references": {
|
||||
# CHECK-NEXT: "_self": {{[0-9]+}},
|
||||
# CHECK-NEXT: "_total": {{[0-9]+}}
|
||||
# CHECK-NEXT: },
|
||||
# CHECK-NEXT: "relations": {
|
||||
# CHECK-NEXT: "_self": {{[0-9]+}},
|
||||
# CHECK-NEXT: "_total": {{[0-9]+}}
|
||||
# CHECK-NEXT: },
|
||||
# CHECK-NEXT: "symbols": {
|
||||
# CHECK-NEXT: "_self": {{[0-9]+}},
|
||||
# CHECK-NEXT: "_total": {{[0-9]+}}
|
||||
# CHECK-NEXT: }
|
||||
# CHECK-NEXT: },
|
||||
# CHECK-NEXT: "_self": {{[0-9]+}},
|
||||
# CHECK-NEXT: "_total": {{[0-9]+}}
|
||||
# CHECK-NEXT: }
|
||||
# CHECK-NEXT: },
|
||||
# CHECK-NEXT: "preamble": {
|
||||
# CHECK-NEXT: "_self": {{[0-9]+}},
|
||||
# CHECK-NEXT: "_total": {{[0-9]+}},
|
||||
# CHECK-NEXT: "index": {
|
||||
# CHECK-NEXT: "_self": {{[0-9]+}},
|
||||
# CHECK-NEXT: "_total": {{[0-9]+}}
|
||||
# CHECK-NEXT: },
|
||||
# CHECK-NEXT: "symbols": {
|
||||
# CHECK-NEXT: "_self": {{[0-9]+}},
|
||||
# CHECK-NEXT: "_total": {{[0-9]+}}
|
||||
# CHECK-NEXT: }
|
||||
# CHECK-NEXT: }
|
||||
# CHECK-NEXT: },
|
||||
# CHECK-NEXT: "tuscheduler": {
|
||||
# CHECK-NEXT: "{{.*}}main.cpp": {
|
||||
# CHECK-NEXT: "_self": {{[0-9]+}},
|
||||
# CHECK-NEXT: "_total": {{[0-9]+}},
|
||||
# CHECK-NEXT: "ast": {
|
||||
# CHECK-NEXT: "_self": {{[0-9]+}},
|
||||
# CHECK-NEXT: "_total": {{[0-9]+}}
|
||||
# CHECK-NEXT: },
|
||||
# CHECK-NEXT: "preamble": {
|
||||
# CHECK-NEXT: "_self": {{[0-9]+}},
|
||||
# CHECK-NEXT: "_total": {{[0-9]+}}
|
||||
# CHECK-NEXT: }
|
||||
# CHECK-NEXT: },
|
||||
# CHECK-NEXT: "_self": {{[0-9]+}},
|
||||
# CHECK-NEXT: "_total": {{[0-9]+}}
|
||||
# CHECK-NEXT: }
|
||||
# CHECK-NEXT: }
|
||||
# CHECK-NEXT: }
|
||||
---
|
||||
{"jsonrpc":"2.0","id":3,"method":"shutdown"}
|
||||
---
|
||||
{"jsonrpc":"2.0","method":"exit"}
|
||||
|
Loading…
Reference in New Issue