brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.9 KiB · 81304fe Raw
222 lines · cpp
1//===- YAMLBench - Benchmark the YAMLParser implementation ----------------===//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-exception6//7//===----------------------------------------------------------------------===//8//9// This program executes the YAMLParser on differently sized YAML texts and10// outputs the run time.11//12//===----------------------------------------------------------------------===//13 14 15#include "llvm/ADT/SmallString.h"16#include "llvm/Support/Casting.h"17#include "llvm/Support/CommandLine.h"18#include "llvm/Support/MemoryBuffer.h"19#include "llvm/Support/SourceMgr.h"20#include "llvm/Support/Timer.h"21#include "llvm/Support/Process.h"22#include "llvm/Support/YAMLParser.h"23#include "llvm/Support/raw_ostream.h"24#include <system_error>25 26using namespace llvm;27 28static cl::opt<bool>29  DumpTokens( "tokens"30            , cl::desc("Print the tokenization of the file.")31            , cl::init(false)32            );33 34static cl::opt<bool>35  DumpCanonical( "canonical"36               , cl::desc("Print the canonical YAML for this file.")37               , cl::init(false)38               );39 40static cl::opt<std::string>41 Input(cl::Positional, cl::desc("<input>"));42 43static cl::opt<bool>44  Verify( "verify"45        , cl::desc(46            "Run a quick verification useful for regression testing")47        , cl::init(false)48        );49 50static cl::opt<unsigned>51  MemoryLimitMB("memory-limit", cl::desc(52                  "Do not use more megabytes of memory"),53                cl::init(1000));54 55static cl::opt<cl::boolOrDefault>56    UseColor("use-color", cl::desc("Emit colored output (default=autodetect)"),57             cl::init(cl::BOU_UNSET));58 59/// Pretty print a tag by replacing tag:yaml.org,2002: with !!.60static std::string prettyTag(yaml::Node *N) {61  std::string Tag = N->getVerbatimTag();62  if (StringRef(Tag).starts_with("tag:yaml.org,2002:")) {63    std::string Ret = "!!";64    Ret += StringRef(Tag).substr(18);65    return Ret;66  }67  std::string Ret = "!<";68  Ret += Tag;69  Ret += ">";70  return Ret;71}72 73static void dumpNode( yaml::Node *n74                    , unsigned Indent = 075                    , bool SuppressFirstIndent = false) {76  if (!n)77    return;78  if (!SuppressFirstIndent)79    outs() << indent(Indent);80  StringRef Anchor = n->getAnchor();81  if (!Anchor.empty())82    outs() << "&" << Anchor << " ";83  if (yaml::ScalarNode *sn = dyn_cast<yaml::ScalarNode>(n)) {84    SmallString<32> Storage;85    StringRef Val = sn->getValue(Storage);86    outs() << prettyTag(n) << " \"" << yaml::escape(Val) << "\"";87  } else if (yaml::BlockScalarNode *BN = dyn_cast<yaml::BlockScalarNode>(n)) {88    outs() << prettyTag(n) << " \"" << yaml::escape(BN->getValue()) << "\"";89  } else if (yaml::SequenceNode *sn = dyn_cast<yaml::SequenceNode>(n)) {90    outs() << prettyTag(n) << " [\n";91    ++Indent;92    for (yaml::SequenceNode::iterator i = sn->begin(), e = sn->end();93                                      i != e; ++i) {94      dumpNode(i, Indent);95      outs() << ",\n";96    }97    --Indent;98    outs() << indent(Indent) << "]";99  } else if (yaml::MappingNode *mn = dyn_cast<yaml::MappingNode>(n)) {100    outs() << prettyTag(n) << " {\n";101    ++Indent;102    for (yaml::MappingNode::iterator i = mn->begin(), e = mn->end();103                                     i != e; ++i) {104      outs() << indent(Indent) << "? ";105      dumpNode(i->getKey(), Indent, true);106      outs() << "\n";107      outs() << indent(Indent) << ": ";108      dumpNode(i->getValue(), Indent, true);109      outs() << ",\n";110    }111    --Indent;112    outs() << indent(Indent) << "}";113  } else if (yaml::AliasNode *an = dyn_cast<yaml::AliasNode>(n)){114    outs() << "*" << an->getName();115  } else if (isa<yaml::NullNode>(n)) {116    outs() << prettyTag(n) << " null";117  }118}119 120static void dumpStream(yaml::Stream &stream) {121  for (yaml::document_iterator di = stream.begin(), de = stream.end(); di != de;122       ++di) {123    outs() << "%YAML 1.2\n"124           << "---\n";125    yaml::Node *n = di->getRoot();126    if (n)127      dumpNode(n);128    else129      break;130    outs() << "\n...\n";131  }132}133 134static void benchmark(llvm::TimerGroup &Group, llvm::StringRef Name,135                      llvm::StringRef Description, llvm::StringRef JSONText) {136  llvm::Timer BaseLine((Name + ".loop").str(), (Description + ": Loop").str(),137                       Group);138  BaseLine.startTimer();139  char C = 0;140  for (llvm::StringRef::iterator I = JSONText.begin(),141                                 E = JSONText.end();142       I != E; ++I) { C += *I; }143  BaseLine.stopTimer();144  volatile char DontOptimizeOut = C; (void)DontOptimizeOut;145 146  llvm::Timer Tokenizing((Name + ".tokenizing").str(),147                         (Description + ": Tokenizing").str(), Group);148  Tokenizing.startTimer();149  {150    yaml::scanTokens(JSONText);151  }152  Tokenizing.stopTimer();153 154  llvm::Timer Parsing((Name + ".parsing").str(),155                      (Description + ": Parsing").str(), Group);156  Parsing.startTimer();157  {158    llvm::SourceMgr SM;159    llvm::yaml::Stream stream(JSONText, SM);160    stream.skip();161  }162  Parsing.stopTimer();163}164 165static std::string createJSONText(size_t MemoryMB, unsigned ValueSize) {166  std::string JSONText;167  llvm::raw_string_ostream Stream(JSONText);168  Stream << "[\n";169  size_t MemoryBytes = MemoryMB * 1024 * 1024;170  while (JSONText.size() < MemoryBytes) {171    Stream << " {\n"172           << "  \"key1\": \"" << std::string(ValueSize, '*') << "\",\n"173           << "  \"key2\": \"" << std::string(ValueSize, '*') << "\",\n"174           << "  \"key3\": \"" << std::string(ValueSize, '*') << "\"\n"175           << " }";176    if (JSONText.size() < MemoryBytes) Stream << ",";177    Stream << "\n";178  }179  Stream << "]\n";180  return JSONText;181}182 183int main(int argc, char **argv) {184  llvm::cl::ParseCommandLineOptions(argc, argv);185  bool ShowColors = UseColor == cl::BOU_UNSET186                        ? sys::Process::StandardOutHasColors()187                        : UseColor == cl::BOU_TRUE;188  if (Input.getNumOccurrences()) {189    ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr =190        MemoryBuffer::getFileOrSTDIN(Input);191    if (!BufOrErr)192      return 1;193    MemoryBuffer &Buf = *BufOrErr.get();194 195    llvm::SourceMgr sm;196    if (DumpTokens) {197      yaml::dumpTokens(Buf.getBuffer(), outs());198    }199 200    if (DumpCanonical) {201      yaml::Stream stream(Buf.getBuffer(), sm, ShowColors);202      dumpStream(stream);203      if (stream.failed())204        return 1;205    }206  }207 208  if (Verify) {209    llvm::TimerGroup Group("yaml", "YAML parser benchmark");210    benchmark(Group, "Fast", "Fast", createJSONText(10, 500));211  } else if (!DumpCanonical && !DumpTokens) {212    llvm::TimerGroup Group("yaml", "YAML parser benchmark");213    benchmark(Group, "Small", "Small Values", createJSONText(MemoryLimitMB, 5));214    benchmark(Group, "Medium", "Medium Values",215              createJSONText(MemoryLimitMB, 500));216    benchmark(Group, "Large", "Large Values",217              createJSONText(MemoryLimitMB, 50000));218  }219 220  return 0;221}222