193210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer//===- YAMLBench - Benchmark the YAMLParser implementation ----------------===//
293210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer//
393210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer//                     The LLVM Compiler Infrastructure
493210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer//
593210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer// This file is distributed under the University of Illinois Open Source
693210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer// License. See LICENSE.TXT for details.
793210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer//
893210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer//===----------------------------------------------------------------------===//
993210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer//
10dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines// This program executes the YAMLParser on differently sized YAML texts and
1193210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer// outputs the run time.
1293210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer//
1393210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer//===----------------------------------------------------------------------===//
1493210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer
1593210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer
1693210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer#include "llvm/ADT/SmallString.h"
1793210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer#include "llvm/Support/Casting.h"
1893210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer#include "llvm/Support/CommandLine.h"
1993210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer#include "llvm/Support/MemoryBuffer.h"
2093210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer#include "llvm/Support/SourceMgr.h"
2193210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer#include "llvm/Support/Timer.h"
2293210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer#include "llvm/Support/YAMLParser.h"
234ffd89fa4d2788611187d1a534d2ed46adf1702cChandler Carruth#include "llvm/Support/raw_ostream.h"
24c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines#include <system_error>
2593210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer
2693210e847a1496b24cef881723e57c489082dcfeMichael J. Spencerusing namespace llvm;
2793210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer
2893210e847a1496b24cef881723e57c489082dcfeMichael J. Spencerstatic cl::opt<bool>
2993210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  DumpTokens( "tokens"
3093210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer            , cl::desc("Print the tokenization of the file.")
3193210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer            , cl::init(false)
3293210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer            );
3393210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer
3493210e847a1496b24cef881723e57c489082dcfeMichael J. Spencerstatic cl::opt<bool>
3593210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  DumpCanonical( "canonical"
3693210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer               , cl::desc("Print the canonical YAML for this file.")
3793210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer               , cl::init(false)
3893210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer               );
3993210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer
4093210e847a1496b24cef881723e57c489082dcfeMichael J. Spencerstatic cl::opt<std::string>
4193210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer Input(cl::Positional, cl::desc("<input>"));
4293210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer
4393210e847a1496b24cef881723e57c489082dcfeMichael J. Spencerstatic cl::opt<bool>
4493210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  Verify( "verify"
4593210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer        , cl::desc(
4693210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer            "Run a quick verification useful for regression testing")
4793210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer        , cl::init(false)
4893210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer        );
4993210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer
5093210e847a1496b24cef881723e57c489082dcfeMichael J. Spencerstatic cl::opt<unsigned>
5193210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  MemoryLimitMB("memory-limit", cl::desc(
5293210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer                  "Do not use more megabytes of memory"),
5393210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer                cl::init(1000));
5493210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer
5593210e847a1496b24cef881723e57c489082dcfeMichael J. Spencerstruct indent {
5693210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  unsigned distance;
5793210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  indent(unsigned d) : distance(d) {}
5893210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer};
5993210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer
6093210e847a1496b24cef881723e57c489082dcfeMichael J. Spencerstatic raw_ostream &operator <<(raw_ostream &os, const indent &in) {
6193210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  for (unsigned i = 0; i < in.distance; ++i)
6293210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    os << "  ";
6393210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  return os;
6493210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer}
6593210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer
6644a4cfb63d87dc0ba778982a1796673ca1513e90Michael J. Spencer/// \brief Pretty print a tag by replacing tag:yaml.org,2002: with !!.
6744a4cfb63d87dc0ba778982a1796673ca1513e90Michael J. Spencerstatic std::string prettyTag(yaml::Node *N) {
6844a4cfb63d87dc0ba778982a1796673ca1513e90Michael J. Spencer  std::string Tag = N->getVerbatimTag();
6944a4cfb63d87dc0ba778982a1796673ca1513e90Michael J. Spencer  if (StringRef(Tag).startswith("tag:yaml.org,2002:")) {
7044a4cfb63d87dc0ba778982a1796673ca1513e90Michael J. Spencer    std::string Ret = "!!";
7144a4cfb63d87dc0ba778982a1796673ca1513e90Michael J. Spencer    Ret += StringRef(Tag).substr(18);
7236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    return std::move(Ret);
7344a4cfb63d87dc0ba778982a1796673ca1513e90Michael J. Spencer  }
7444a4cfb63d87dc0ba778982a1796673ca1513e90Michael J. Spencer  std::string Ret = "!<";
7544a4cfb63d87dc0ba778982a1796673ca1513e90Michael J. Spencer  Ret += Tag;
7644a4cfb63d87dc0ba778982a1796673ca1513e90Michael J. Spencer  Ret += ">";
7744a4cfb63d87dc0ba778982a1796673ca1513e90Michael J. Spencer  return Ret;
7844a4cfb63d87dc0ba778982a1796673ca1513e90Michael J. Spencer}
7944a4cfb63d87dc0ba778982a1796673ca1513e90Michael J. Spencer
8093210e847a1496b24cef881723e57c489082dcfeMichael J. Spencerstatic void dumpNode( yaml::Node *n
8193210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer                    , unsigned Indent = 0
8293210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer                    , bool SuppressFirstIndent = false) {
8393210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  if (!n)
8493210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    return;
8593210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  if (!SuppressFirstIndent)
8693210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    outs() << indent(Indent);
8793210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  StringRef Anchor = n->getAnchor();
8893210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  if (!Anchor.empty())
8993210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    outs() << "&" << Anchor << " ";
9093210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  if (yaml::ScalarNode *sn = dyn_cast<yaml::ScalarNode>(n)) {
9193210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    SmallString<32> Storage;
9293210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    StringRef Val = sn->getValue(Storage);
9344a4cfb63d87dc0ba778982a1796673ca1513e90Michael J. Spencer    outs() << prettyTag(n) << " \"" << yaml::escape(Val) << "\"";
9493210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  } else if (yaml::SequenceNode *sn = dyn_cast<yaml::SequenceNode>(n)) {
9544a4cfb63d87dc0ba778982a1796673ca1513e90Michael J. Spencer    outs() << prettyTag(n) << " [\n";
9693210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    ++Indent;
9793210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    for (yaml::SequenceNode::iterator i = sn->begin(), e = sn->end();
9893210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer                                      i != e; ++i) {
9993210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer      dumpNode(i, Indent);
10093210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer      outs() << ",\n";
10193210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    }
10293210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    --Indent;
10393210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    outs() << indent(Indent) << "]";
10493210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  } else if (yaml::MappingNode *mn = dyn_cast<yaml::MappingNode>(n)) {
10544a4cfb63d87dc0ba778982a1796673ca1513e90Michael J. Spencer    outs() << prettyTag(n) << " {\n";
10693210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    ++Indent;
10793210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    for (yaml::MappingNode::iterator i = mn->begin(), e = mn->end();
10893210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer                                     i != e; ++i) {
10993210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer      outs() << indent(Indent) << "? ";
11093210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer      dumpNode(i->getKey(), Indent, true);
11193210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer      outs() << "\n";
11293210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer      outs() << indent(Indent) << ": ";
11393210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer      dumpNode(i->getValue(), Indent, true);
11493210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer      outs() << ",\n";
11593210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    }
11693210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    --Indent;
11793210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    outs() << indent(Indent) << "}";
11893210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  } else if (yaml::AliasNode *an = dyn_cast<yaml::AliasNode>(n)){
11993210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    outs() << "*" << an->getName();
1202c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar  } else if (isa<yaml::NullNode>(n)) {
12144a4cfb63d87dc0ba778982a1796673ca1513e90Michael J. Spencer    outs() << prettyTag(n) << " null";
12293210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  }
12393210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer}
12493210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer
12593210e847a1496b24cef881723e57c489082dcfeMichael J. Spencerstatic void dumpStream(yaml::Stream &stream) {
12693210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  for (yaml::document_iterator di = stream.begin(), de = stream.end(); di != de;
12793210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer       ++di) {
12893210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    outs() << "%YAML 1.2\n"
12993210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer           << "---\n";
13093210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    yaml::Node *n = di->getRoot();
13193210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    if (n)
13293210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer      dumpNode(n);
13393210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    else
13493210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer      break;
13593210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    outs() << "\n...\n";
13693210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  }
13793210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer}
13893210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer
13993210e847a1496b24cef881723e57c489082dcfeMichael J. Spencerstatic void benchmark( llvm::TimerGroup &Group
14093210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer                     , llvm::StringRef Name
14193210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer                     , llvm::StringRef JSONText) {
14293210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  llvm::Timer BaseLine((Name + ": Loop").str(), Group);
14393210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  BaseLine.startTimer();
14493210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  char C = 0;
14593210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  for (llvm::StringRef::iterator I = JSONText.begin(),
14693210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer                                 E = JSONText.end();
14793210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer       I != E; ++I) { C += *I; }
14893210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  BaseLine.stopTimer();
14993210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  volatile char DontOptimizeOut = C; (void)DontOptimizeOut;
15093210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer
15193210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  llvm::Timer Tokenizing((Name + ": Tokenizing").str(), Group);
15293210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  Tokenizing.startTimer();
15393210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  {
15493210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    yaml::scanTokens(JSONText);
15593210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  }
15693210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  Tokenizing.stopTimer();
15793210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer
15893210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  llvm::Timer Parsing((Name + ": Parsing").str(), Group);
15993210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  Parsing.startTimer();
16093210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  {
16193210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    llvm::SourceMgr SM;
16293210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    llvm::yaml::Stream stream(JSONText, SM);
16393210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    stream.skip();
16493210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  }
16593210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  Parsing.stopTimer();
16693210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer}
16793210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer
16893210e847a1496b24cef881723e57c489082dcfeMichael J. Spencerstatic std::string createJSONText(size_t MemoryMB, unsigned ValueSize) {
16993210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  std::string JSONText;
17093210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  llvm::raw_string_ostream Stream(JSONText);
17193210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  Stream << "[\n";
17293210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  size_t MemoryBytes = MemoryMB * 1024 * 1024;
17393210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  while (JSONText.size() < MemoryBytes) {
17493210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    Stream << " {\n"
17593210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer           << "  \"key1\": \"" << std::string(ValueSize, '*') << "\",\n"
17693210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer           << "  \"key2\": \"" << std::string(ValueSize, '*') << "\",\n"
17793210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer           << "  \"key3\": \"" << std::string(ValueSize, '*') << "\"\n"
17893210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer           << " }";
17993210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    Stream.flush();
18093210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    if (JSONText.size() < MemoryBytes) Stream << ",";
18193210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    Stream << "\n";
18293210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  }
18393210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  Stream << "]\n";
18493210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  Stream.flush();
18593210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  return JSONText;
18693210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer}
18793210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer
18893210e847a1496b24cef881723e57c489082dcfeMichael J. Spencerint main(int argc, char **argv) {
18993210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  llvm::cl::ParseCommandLineOptions(argc, argv);
19093210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  if (Input.getNumOccurrences()) {
191c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr =
192c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines        MemoryBuffer::getFileOrSTDIN(Input);
193c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    if (!BufOrErr)
19493210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer      return 1;
19537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    MemoryBuffer &Buf = *BufOrErr.get();
19693210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer
19793210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    llvm::SourceMgr sm;
19893210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    if (DumpTokens) {
19937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      yaml::dumpTokens(Buf.getBuffer(), outs());
20093210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    }
20193210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer
20293210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    if (DumpCanonical) {
20337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      yaml::Stream stream(Buf.getBuffer(), sm);
20493210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer      dumpStream(stream);
20593210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    }
20693210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  }
20793210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer
20893210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  if (Verify) {
20993210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    llvm::TimerGroup Group("YAML parser benchmark");
21093210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    benchmark(Group, "Fast", createJSONText(10, 500));
21193210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  } else if (!DumpCanonical && !DumpTokens) {
21293210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    llvm::TimerGroup Group("YAML parser benchmark");
21393210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    benchmark(Group, "Small Values", createJSONText(MemoryLimitMB, 5));
21493210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    benchmark(Group, "Medium Values", createJSONText(MemoryLimitMB, 500));
21593210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    benchmark(Group, "Large Values", createJSONText(MemoryLimitMB, 50000));
21693210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  }
21793210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer
21893210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  return 0;
21993210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer}
220