clang-tools 23.0.0git
ClangDocBenchmark.cpp
Go to the documentation of this file.
1//===----------------------------------------------------------------------===//
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/// \file
10/// This file contains basic benchmarks for clang-doc's implementation and
11/// library components.
12///
13//===----------------------------------------------------------------------===//
14
15#include "BitcodeReader.h"
16#include "BitcodeWriter.h"
17#include "ClangDoc.h"
18#include "Generators.h"
19#include "Representation.h"
20#include "Serialize.h"
21#include "benchmark/benchmark.h"
22#include "clang/AST/ASTContext.h"
23#include "clang/AST/RecursiveASTVisitor.h"
24#include "clang/Tooling/Execution.h"
25#include "clang/Tooling/Tooling.h"
26#include "llvm/Bitstream/BitstreamWriter.h"
27#include <string>
28#include <vector>
29
30namespace clang {
31namespace doc {
32
33class BenchmarkVisitor : public RecursiveASTVisitor<BenchmarkVisitor> {
34public:
35 explicit BenchmarkVisitor(const FunctionDecl *&Func) : Func(Func) {}
36
37 bool VisitFunctionDecl(const FunctionDecl *D) {
38 if (D->getName() == "f") {
39 Func = D;
40 return false;
41 }
42 return true;
43 }
44
45private:
46 const FunctionDecl *&Func;
47};
48
49// --- Mapper Benchmarks ---
50
51static void BM_EmitInfoFunction(benchmark::State &State) {
52 std::string Code = "void f() {}";
53 OwnedPtr<clang::ASTUnit> AST = clang::tooling::buildASTFromCode(Code);
54 const FunctionDecl *Func = nullptr;
55 BenchmarkVisitor Visitor(Func);
56 Visitor.TraverseDecl(AST->getASTContext().getTranslationUnitDecl());
57 assert(Func);
58
59 clang::comments::FullComment *FC = nullptr;
60 Location Loc;
61
62 for (auto _ : State) {
63 serialize::Serializer Serializer;
64 auto Result = Serializer.emitInfo(Func, FC, Loc, /*PublicOnly=*/false);
65 benchmark::DoNotOptimize(Result);
66 }
67}
69
70static void BM_Mapper_Scale(benchmark::State &State) {
71 std::string Code;
72 for (int i = 0; i < State.range(0); ++i) {
73 Code += "void f" + std::to_string(i) + "() {}\n";
74 }
75
76 IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
77 DiagnosticOptions DiagOpts;
78 DiagnosticsEngine Diags(DiagID, DiagOpts, new IgnoringDiagConsumer());
79
80 for (auto _ : State) {
81 tooling::InMemoryToolResults Results;
82 tooling::ExecutionContext ECtx(&Results);
83 ClangDocContext CDCtx(&ECtx, "test-project", false, "", "", "", "", "", {},
84 Diags, OutputFormatTy::json, false);
85 auto ActionFactory = doc::newMapperActionFactory(CDCtx);
86 OwnedPtr<FrontendAction> Action = ActionFactory->create();
87 tooling::runToolOnCode(std::move(Action), Code, "test.cpp");
88 }
89}
90BENCHMARK(BM_Mapper_Scale)->Range(10, 10000);
91
92// --- Reducer Benchmarks ---
93
94static void BM_SerializeFunctionInfo(benchmark::State &State) {
96 I->Name = "f";
97 I->DefLoc = Location(0, 0, "test.cpp");
98 I->ReturnType = TypeInfo("void");
100
101 IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
102 DiagnosticOptions DiagOpts;
103 DiagnosticsEngine Diags(DiagID, DiagOpts, new IgnoringDiagConsumer());
104
105 OwnedPtr<Info> InfoPtr = std::move(I);
106
107 for (auto _ : State) {
108 auto Result = serialize::serialize(InfoPtr, Diags);
109 benchmark::DoNotOptimize(Result);
110 }
111}
113
114static void BM_MergeInfos_Scale(benchmark::State &State) {
115 SymbolID USR = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
116 11, 12, 13, 14, 15, 16, 17, 18, 19, 20};
117
118 for (auto _ : State) {
119 State.PauseTiming();
121 Input.reserve(State.range(0));
122 for (int i = 0; i < State.range(0); ++i) {
123 auto I = allocatePtr<FunctionInfo>();
124 I->Name = "f";
125 I->USR = USR;
126 I->DefLoc = Location(10, i, "test.cpp");
127 Input.push_back(std::move(I));
128 }
129 State.ResumeTiming();
130
131 auto Result = doc::mergeInfos(Input);
132 if (!Result) {
133 State.SkipWithError("mergeInfos failed");
134 llvm::consumeError(Result.takeError());
135 }
136 benchmark::DoNotOptimize(Result);
137 }
138}
140
141static void BM_BitcodeReader_Scale(benchmark::State &State) {
142 int NumRecords = State.range(0);
143
144 SmallString<0> Buffer;
145 llvm::BitstreamWriter Stream(Buffer);
146 IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
147 DiagnosticOptions DiagOpts;
148 DiagnosticsEngine Diags(DiagID, DiagOpts, new IgnoringDiagConsumer());
149
150 ClangDocBitcodeWriter Writer(Stream, Diags);
151 for (int i = 0; i < NumRecords; ++i) {
152 RecordInfo RI;
153 RI.Name = "Record" + std::to_string(i);
154 RI.USR = {(uint8_t)(i & 0xFF)};
155 Writer.emitBlock(RI);
156 }
157
158 std::string BitcodeData = Buffer.str().str();
159
160 for (auto _ : State) {
161 llvm::BitstreamCursor Cursor(llvm::ArrayRef<uint8_t>(
162 (const uint8_t *)BitcodeData.data(), BitcodeData.size()));
163 ClangDocBitcodeReader Reader(Cursor, Diags);
164 auto Result = Reader.readBitcode();
165 if (!Result) {
166 State.SkipWithError("readBitcode failed");
167 llvm::consumeError(Result.takeError());
168 }
169 benchmark::DoNotOptimize(Result);
170 }
171}
173
174// --- Generator Benchmarks ---
175
176static void BM_JSONGenerator_Scale(benchmark::State &State) {
177 auto G = doc::findGeneratorByName("json");
178 if (!G) {
179 State.SkipWithError("JSON Generator not found");
180 llvm::consumeError(G.takeError());
181 return;
182 }
183
184 int NumRecords = State.range(0);
185 auto NI = allocatePtr<NamespaceInfo>();
186 NI->Name = "GlobalNamespace";
187 for (int i = 0; i < NumRecords; ++i) {
188 NI->Children.Records.emplace_back(SymbolID{(uint8_t)(i & 0xFF)},
189 "Record" + std::to_string(i),
191 }
192
193 IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
194 DiagnosticOptions DiagOpts;
195 DiagnosticsEngine Diags(DiagID, DiagOpts, new IgnoringDiagConsumer());
196 ClangDocContext CDCtx(nullptr, "test-project", false, "", "", "", "", "", {},
197 Diags, OutputFormatTy::json, false);
198
199 std::string Output;
200 llvm::raw_string_ostream OS(Output);
201
202 for (auto _ : State) {
203 Output.clear();
204 auto Err = (*G)->generateDocForInfo(getPtr(NI), OS, CDCtx);
205 if (Err) {
206 State.SkipWithError("generateDocForInfo failed");
207 llvm::consumeError(std::move(Err));
208 }
209 benchmark::DoNotOptimize(Output);
210 }
211}
213
214// --- Index Benchmarks ---
215
216static void BM_Index_Insertion(benchmark::State &State) {
217 for (auto _ : State) {
218 Index Idx;
219 for (int i = 0; i < State.range(0); ++i) {
220 RecordInfo I;
221 I.Name = "Record" + std::to_string(i);
222 // Vary USR to ensure unique entries
223 I.USR = {(uint8_t)(i & 0xFF), (uint8_t)((i >> 8) & 0xFF)};
224 I.Path = "path/to/record";
226 }
227 benchmark::DoNotOptimize(Idx);
228 }
229}
230BENCHMARK(BM_Index_Insertion)->Range(10, 10000);
231
232} // namespace doc
233} // namespace clang
234
BENCHMARK_MAIN()
bool VisitFunctionDecl(const FunctionDecl *D)
BenchmarkVisitor(const FunctionDecl *&Func)
llvm::Expected< OwningPtrArray< Info > > readBitcode()
void emitBlock(const NamespaceInfo &I)
static void addInfoToIndex(Index &Idx, const doc::Info *Info)
std::pair< OwnedPtr< Info >, OwnedPtr< Info > > emitInfo(const NamespaceDecl *D, const FullComment *FC, Location Loc, bool PublicOnly)
static std::string serialize(T &I, DiagnosticsEngine &Diags)
static void BM_BitcodeReader_Scale(benchmark::State &State)
static void BM_MergeInfos_Scale(benchmark::State &State)
llvm::Expected< OwnedPtr< Info > > mergeInfos(OwningPtrArray< Info > &Values)
llvm::Expected< std::unique_ptr< Generator > > findGeneratorByName(llvm::StringRef Format)
OwnedPtr< tooling::FrontendActionFactory > newMapperActionFactory(ClangDocContext CDCtx)
Definition ClangDoc.cpp:52
std::unique_ptr< T > OwnedPtr
T * getPtr(const OwnedPtr< T > &O)
BENCHMARK(BM_EmitInfoFunction)
std::vector< OwnedPtr< T > > OwningPtrArray
static void BM_EmitInfoFunction(benchmark::State &State)
static void BM_Index_Insertion(benchmark::State &State)
static void BM_SerializeFunctionInfo(benchmark::State &State)
OwnedPtr< T > allocatePtr(Args &&...args)
std::array< uint8_t, 20 > SymbolID
static void BM_JSONGenerator_Scale(benchmark::State &State)
static void BM_Mapper_Scale(benchmark::State &State)
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
SmallString< 16 > Name
llvm::SmallString< 128 > Path