From be895d5768d5e12581f158b9522b167c833796d8 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Sun, 8 May 2022 22:14:27 +0200 Subject: [PATCH] [pseudo] Add benchmarks for pseudoparser. Running on SemaDecl.cpp with the cxx.bnf grammar: ``` -------------------------------------------------------------- Benchmark Time CPU Iterations -------------------------------------------------------------- runParseBNFGrammar 649389 ns 649365 ns 1013 runBuildLR 34591903 ns 34591380 ns 20 runPreprocessTokens 11418744 ns 11418703 ns 61 bytes_per_second=63.8971M/s runGLRParse 282996863 ns 282988726 ns 2 bytes_per_second=2.57827M/s runParseOverall 294969719 ns 294951870 ns 2 bytes_per_second=2.4737M/s ``` Differential Revision: https://reviews.llvm.org/D125226 --- clang-tools-extra/pseudo/CMakeLists.txt | 1 + clang-tools-extra/pseudo/benchmarks/Benchmark.cpp | 139 +++++++++++++++++++++ clang-tools-extra/pseudo/benchmarks/CMakeLists.txt | 7 ++ 3 files changed, 147 insertions(+) create mode 100644 clang-tools-extra/pseudo/benchmarks/Benchmark.cpp create mode 100644 clang-tools-extra/pseudo/benchmarks/CMakeLists.txt diff --git a/clang-tools-extra/pseudo/CMakeLists.txt b/clang-tools-extra/pseudo/CMakeLists.txt index e94737f..0891cc0 100644 --- a/clang-tools-extra/pseudo/CMakeLists.txt +++ b/clang-tools-extra/pseudo/CMakeLists.txt @@ -3,6 +3,7 @@ include_directories(${CMAKE_CURRENT_BINARY_DIR}/include) add_subdirectory(lib) add_subdirectory(tool) add_subdirectory(fuzzer) +add_subdirectory(benchmarks) if(CLANG_INCLUDE_TESTS) add_subdirectory(unittests) add_subdirectory(test) diff --git a/clang-tools-extra/pseudo/benchmarks/Benchmark.cpp b/clang-tools-extra/pseudo/benchmarks/Benchmark.cpp new file mode 100644 index 0000000..9568f76 --- /dev/null +++ b/clang-tools-extra/pseudo/benchmarks/Benchmark.cpp @@ -0,0 +1,139 @@ +//===--- Benchmark.cpp - clang pseudoparser 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 +// +//===----------------------------------------------------------------------===// +// +// Benchmark for the overall pseudoparser performance, it also includes other +// important pieces of the pseudoparser (grammar compliation, LR table build +// etc). +// +// Note: make sure we build it in Relase mode. +// +// Usage: +// tools/clang/tools/extra/pseudo/benchmarks/ClangPseudoBenchmark \ +// --grammar=/path/to/cxx.bnf --source=/patch/to/source-to-parse.cpp \ +// --benchmark_filter=runParseOverall +// +//===----------------------------------------------------------------------===// + +#include "benchmark/benchmark.h" +#include "clang-pseudo/DirectiveTree.h" +#include "clang-pseudo/Forest.h" +#include "clang-pseudo/GLR.h" +#include "clang-pseudo/Grammar.h" +#include "clang-pseudo/LRTable.h" +#include "clang-pseudo/Token.h" +#include "clang/Basic/LangOptions.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/ErrorOr.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/raw_ostream.h" +#include + +using llvm::cl::desc; +using llvm::cl::init; +using llvm::cl::opt; + +static opt GrammarFile("grammar", + desc("Parse and check a BNF grammar file."), + init("")); +static opt Source("source", desc("Source file")); + +namespace clang { +namespace pseudo { +namespace { + +const std::string *GrammarText = nullptr; +const std::string *SourceText = nullptr; +const Grammar *G = nullptr; + +void setupGrammarAndSource() { + auto ReadFile = [](llvm::StringRef FilePath) -> std::string { + llvm::ErrorOr> GrammarText = + llvm::MemoryBuffer::getFile(FilePath); + if (std::error_code EC = GrammarText.getError()) { + llvm::errs() << "Error: can't read file '" << FilePath + << "': " << EC.message() << "\n"; + std::exit(1); + } + return GrammarText.get()->getBuffer().str(); + }; + GrammarText = new std::string(ReadFile(GrammarFile)); + SourceText = new std::string(ReadFile(Source)); + std::vector Diags; + G = Grammar::parseBNF(*GrammarText, Diags).release(); +} + +static void runParseBNFGrammar(benchmark::State &State) { + std::vector Diags; + for (auto _ : State) + Grammar::parseBNF(*GrammarText, Diags); +} +BENCHMARK(runParseBNFGrammar); + +static void runBuildLR(benchmark::State &State) { + for (auto _ : State) + clang::pseudo::LRTable::buildSLR(*G); +} +BENCHMARK(runBuildLR); + +TokenStream parseableTokenStream() { + clang::LangOptions LangOpts = genericLangOpts(); + TokenStream RawStream = clang::pseudo::lex(*SourceText, LangOpts); + auto DirectiveStructure = DirectiveTree::parse(RawStream); + clang::pseudo::chooseConditionalBranches(DirectiveStructure, RawStream); + TokenStream Cook = + cook(DirectiveStructure.stripDirectives(RawStream), LangOpts); + return clang::pseudo::stripComments(Cook); +} + +static void runPreprocessTokens(benchmark::State &State) { + for (auto _ : State) + parseableTokenStream(); + State.SetBytesProcessed(static_cast(State.iterations()) * + SourceText->size()); +} +BENCHMARK(runPreprocessTokens); + +static void runGLRParse(benchmark::State &State) { + clang::LangOptions LangOpts = genericLangOpts(); + LRTable Table = clang::pseudo::LRTable::buildSLR(*G); + TokenStream ParseableStream = parseableTokenStream(); + for (auto _ : State) { + pseudo::ForestArena Forest; + pseudo::GSS GSS; + glrParse(ParseableStream, ParseParams{*G, Table, Forest, GSS}); + } + State.SetBytesProcessed(static_cast(State.iterations()) * + SourceText->size()); +} +BENCHMARK(runGLRParse); + +static void runParseOverall(benchmark::State &State) { + clang::LangOptions LangOpts = genericLangOpts(); + LRTable Table = clang::pseudo::LRTable::buildSLR(*G); + for (auto _ : State) { + pseudo::ForestArena Forest; + pseudo::GSS GSS; + glrParse(parseableTokenStream(), ParseParams{*G, Table, Forest, GSS}); + } + State.SetBytesProcessed(static_cast(State.iterations()) * + SourceText->size()); +} +BENCHMARK(runParseOverall); + +} // namespace +} // namespace pseudo +} // namespace clang + +int main(int argc, char *argv[]) { + benchmark::Initialize(&argc, argv); + llvm::cl::ParseCommandLineOptions(argc, argv); + clang::pseudo::setupGrammarAndSource(); + benchmark::RunSpecifiedBenchmarks(); + return 0; +} diff --git a/clang-tools-extra/pseudo/benchmarks/CMakeLists.txt b/clang-tools-extra/pseudo/benchmarks/CMakeLists.txt new file mode 100644 index 0000000..2080406 --- /dev/null +++ b/clang-tools-extra/pseudo/benchmarks/CMakeLists.txt @@ -0,0 +1,7 @@ +add_benchmark(ClangPseudoBenchmark Benchmark.cpp) + +target_link_libraries(ClangPseudoBenchmark + PRIVATE + clangPseudo + LLVMSupport + ) -- 2.7.4