1 //===--- Benchmark.cpp - clang pseudoparser benchmarks ---------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 // Benchmark for the overall pseudoparser performance, it also includes other
10 // important pieces of the pseudoparser (grammar compliation, LR table build
13 // Note: make sure to build the benchmark in Release mode.
16 // tools/clang/tools/extra/pseudo/benchmarks/ClangPseudoBenchmark \
17 // --grammar=../clang-tools-extra/pseudo/lib/cxx.bnf \
18 // --source=../clang/lib/Sema/SemaDecl.cpp
20 //===----------------------------------------------------------------------===//
22 #include "benchmark/benchmark.h"
23 #include "clang-pseudo/Bracket.h"
24 #include "clang-pseudo/DirectiveTree.h"
25 #include "clang-pseudo/Forest.h"
26 #include "clang-pseudo/GLR.h"
27 #include "clang-pseudo/Token.h"
28 #include "clang-pseudo/cli/CLI.h"
29 #include "clang-pseudo/grammar/Grammar.h"
30 #include "clang-pseudo/grammar/LRTable.h"
31 #include "clang/Basic/LangOptions.h"
32 #include "llvm/ADT/StringRef.h"
33 #include "llvm/Support/CommandLine.h"
34 #include "llvm/Support/ErrorOr.h"
35 #include "llvm/Support/MemoryBuffer.h"
36 #include "llvm/Support/raw_ostream.h"
41 using llvm::cl::Required
;
43 static opt
<std::string
> Source("source", desc("Source file"), Required
);
50 const std::string
*SourceText
= nullptr;
51 const Language
*Lang
= nullptr;
54 auto ReadFile
= [](llvm::StringRef FilePath
) -> std::string
{
55 llvm::ErrorOr
<std::unique_ptr
<llvm::MemoryBuffer
>> GrammarText
=
56 llvm::MemoryBuffer::getFile(FilePath
);
57 if (std::error_code EC
= GrammarText
.getError()) {
58 llvm::errs() << "Error: can't read file '" << FilePath
59 << "': " << EC
.message() << "\n";
62 return GrammarText
.get()->getBuffer().str();
64 SourceText
= new std::string(ReadFile(Source
));
65 Lang
= &getLanguageFromFlags();
68 static void buildSLR(benchmark::State
&State
) {
70 LRTable::buildSLR(Lang
->G
);
74 TokenStream
lexAndPreprocess() {
75 clang::LangOptions LangOpts
= genericLangOpts();
76 TokenStream RawStream
= pseudo::lex(*SourceText
, LangOpts
);
77 auto DirectiveStructure
= DirectiveTree::parse(RawStream
);
78 chooseConditionalBranches(DirectiveStructure
, RawStream
);
80 cook(DirectiveStructure
.stripDirectives(RawStream
), LangOpts
);
81 auto Stream
= stripComments(Cook
);
86 static void lex(benchmark::State
&State
) {
87 clang::LangOptions LangOpts
= genericLangOpts();
89 clang::pseudo::lex(*SourceText
, LangOpts
);
90 State
.SetBytesProcessed(static_cast<uint64_t>(State
.iterations()) *
95 static void pairBrackets(benchmark::State
&State
) {
96 clang::LangOptions LangOpts
= genericLangOpts();
97 auto Stream
= clang::pseudo::lex(*SourceText
, LangOpts
);
100 State
.SetBytesProcessed(static_cast<uint64_t>(State
.iterations()) *
103 BENCHMARK(pairBrackets
);
105 static void preprocess(benchmark::State
&State
) {
106 clang::LangOptions LangOpts
= genericLangOpts();
107 TokenStream RawStream
= clang::pseudo::lex(*SourceText
, LangOpts
);
108 for (auto _
: State
) {
109 auto DirectiveStructure
= DirectiveTree::parse(RawStream
);
110 chooseConditionalBranches(DirectiveStructure
, RawStream
);
112 cook(DirectiveStructure
.stripDirectives(RawStream
), LangOpts
));
114 State
.SetBytesProcessed(static_cast<uint64_t>(State
.iterations()) *
117 BENCHMARK(preprocess
);
119 static void glrParse(benchmark::State
&State
) {
120 SymbolID StartSymbol
= *Lang
->G
.findNonterminal("translation-unit");
121 TokenStream Stream
= lexAndPreprocess();
122 for (auto _
: State
) {
123 pseudo::ForestArena Forest
;
125 pseudo::glrParse(ParseParams
{Stream
, Forest
, GSS
}, StartSymbol
, *Lang
);
127 State
.SetBytesProcessed(static_cast<uint64_t>(State
.iterations()) *
132 static void full(benchmark::State
&State
) {
133 SymbolID StartSymbol
= *Lang
->G
.findNonterminal("translation-unit");
134 for (auto _
: State
) {
135 TokenStream Stream
= lexAndPreprocess();
136 pseudo::ForestArena Forest
;
138 pseudo::glrParse(ParseParams
{Stream
, Forest
, GSS
}, StartSymbol
, *Lang
);
140 State
.SetBytesProcessed(static_cast<uint64_t>(State
.iterations()) *
147 } // namespace pseudo
150 int main(int argc
, char *argv
[]) {
151 benchmark::Initialize(&argc
, argv
);
152 llvm::cl::ParseCommandLineOptions(argc
, argv
);
153 clang::pseudo::bench::setup();
154 benchmark::RunSpecifiedBenchmarks();