| //===--- IndexBenchmark.cpp - Clangd index benchmarks -----------*- C++ -*-===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "../index/Serialization.h" |
| #include "../index/dex/Dex.h" |
| #include "benchmark/benchmark.h" |
| #include "llvm/ADT/SmallVector.h" |
| #include "llvm/ADT/StringRef.h" |
| #include "llvm/Support/Path.h" |
| #include "llvm/Support/Regex.h" |
| #include <string> |
| |
| const char *IndexFilename; |
| const char *RequestsFilename; |
| |
| namespace clang { |
| namespace clangd { |
| namespace { |
| |
| std::unique_ptr<SymbolIndex> buildMem() { |
| return loadIndex(IndexFilename, /*UseDex=*/false); |
| } |
| |
| std::unique_ptr<SymbolIndex> buildDex() { |
| return loadIndex(IndexFilename, /*UseDex=*/true); |
| } |
| |
| // Reads JSON array of serialized FuzzyFindRequest's from user-provided file. |
| std::vector<FuzzyFindRequest> extractQueriesFromLogs() { |
| |
| auto Buffer = llvm::MemoryBuffer::getFile(RequestsFilename); |
| if (!Buffer) { |
| llvm::errs() << "Error cannot open JSON request file:" << RequestsFilename |
| << ": " << Buffer.getError().message() << "\n"; |
| exit(1); |
| } |
| |
| StringRef Log = Buffer.get()->getBuffer(); |
| |
| std::vector<FuzzyFindRequest> Requests; |
| auto JSONArray = llvm::json::parse(Log); |
| |
| // Panic if the provided file couldn't be parsed. |
| if (!JSONArray) { |
| llvm::errs() << "Error when parsing JSON requests file: " |
| << llvm::toString(JSONArray.takeError()); |
| exit(1); |
| } |
| if (!JSONArray->getAsArray()) { |
| llvm::errs() << "Error: top-level value is not a JSON array: " << Log |
| << '\n'; |
| exit(1); |
| } |
| |
| for (const auto &Item : *JSONArray->getAsArray()) { |
| FuzzyFindRequest Request; |
| // Panic if the provided file couldn't be parsed. |
| llvm::json::Path::Root Root("FuzzyFindRequest"); |
| if (!fromJSON(Item, Request, Root)) { |
| llvm::errs() << llvm::toString(Root.getError()) << "\n"; |
| Root.printErrorContext(Item, llvm::errs()); |
| exit(1); |
| } |
| Requests.push_back(Request); |
| } |
| return Requests; |
| } |
| |
| static void MemQueries(benchmark::State &State) { |
| const auto Mem = buildMem(); |
| const auto Requests = extractQueriesFromLogs(); |
| for (auto _ : State) |
| for (const auto &Request : Requests) |
| Mem->fuzzyFind(Request, [](const Symbol &S) {}); |
| } |
| BENCHMARK(MemQueries); |
| |
| static void DexQueries(benchmark::State &State) { |
| const auto Dex = buildDex(); |
| const auto Requests = extractQueriesFromLogs(); |
| for (auto _ : State) |
| for (const auto &Request : Requests) |
| Dex->fuzzyFind(Request, [](const Symbol &S) {}); |
| } |
| BENCHMARK(DexQueries); |
| |
| static void DexBuild(benchmark::State &State) { |
| for (auto _ : State) |
| buildDex(); |
| } |
| BENCHMARK(DexBuild); |
| |
| } // namespace |
| } // namespace clangd |
| } // namespace clang |
| |
| // FIXME(kbobyrev): Add index building time benchmarks. |
| // FIXME(kbobyrev): Add memory consumption "benchmarks" by manually measuring |
| // in-memory index size and reporting it as time. |
| // FIXME(kbobyrev): Create a logger wrapper to suppress debugging info printer. |
| int main(int argc, char *argv[]) { |
| if (argc < 3) { |
| llvm::errs() << "Usage: " << argv[0] |
| << " global-symbol-index.dex requests.json " |
| "BENCHMARK_OPTIONS...\n"; |
| return -1; |
| } |
| IndexFilename = argv[1]; |
| RequestsFilename = argv[2]; |
| // Trim first two arguments of the benchmark invocation and pretend no |
| // arguments were passed in the first place. |
| argv[2] = argv[0]; |
| argv += 2; |
| argc -= 2; |
| ::benchmark::Initialize(&argc, argv); |
| ::benchmark::RunSpecifiedBenchmarks(); |
| } |