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//
1093210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer// This program executes the YAMLParser on differntly 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/raw_ostream.h"
2193210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer#include "llvm/Support/SourceMgr.h"
2293210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer#include "llvm/Support/system_error.h"
2393210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer#include "llvm/Support/Timer.h"
2493210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer#include "llvm/Support/YAMLParser.h"
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
6693210e847a1496b24cef881723e57c489082dcfeMichael J. Spencerstatic void dumpNode( yaml::Node *n
6793210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer                    , unsigned Indent = 0
6893210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer                    , bool SuppressFirstIndent = false) {
6993210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  if (!n)
7093210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    return;
7193210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  if (!SuppressFirstIndent)
7293210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    outs() << indent(Indent);
7393210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  StringRef Anchor = n->getAnchor();
7493210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  if (!Anchor.empty())
7593210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    outs() << "&" << Anchor << " ";
7693210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  if (yaml::ScalarNode *sn = dyn_cast<yaml::ScalarNode>(n)) {
7793210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    SmallString<32> Storage;
7893210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    StringRef Val = sn->getValue(Storage);
7993210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    outs() << "!!str \"" << yaml::escape(Val) << "\"";
8093210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  } else if (yaml::SequenceNode *sn = dyn_cast<yaml::SequenceNode>(n)) {
8193210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    outs() << "!!seq [\n";
8293210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    ++Indent;
8393210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    for (yaml::SequenceNode::iterator i = sn->begin(), e = sn->end();
8493210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer                                      i != e; ++i) {
8593210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer      dumpNode(i, Indent);
8693210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer      outs() << ",\n";
8793210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    }
8893210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    --Indent;
8993210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    outs() << indent(Indent) << "]";
9093210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  } else if (yaml::MappingNode *mn = dyn_cast<yaml::MappingNode>(n)) {
9193210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    outs() << "!!map {\n";
9293210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    ++Indent;
9393210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    for (yaml::MappingNode::iterator i = mn->begin(), e = mn->end();
9493210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer                                     i != e; ++i) {
9593210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer      outs() << indent(Indent) << "? ";
9693210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer      dumpNode(i->getKey(), Indent, true);
9793210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer      outs() << "\n";
9893210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer      outs() << indent(Indent) << ": ";
9993210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer      dumpNode(i->getValue(), Indent, true);
10093210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer      outs() << ",\n";
10193210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    }
10293210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    --Indent;
10393210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    outs() << indent(Indent) << "}";
10493210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  } else if (yaml::AliasNode *an = dyn_cast<yaml::AliasNode>(n)){
10593210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    outs() << "*" << an->getName();
10693210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  } else if (dyn_cast<yaml::NullNode>(n)) {
10793210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    outs() << "!!null null";
10893210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  }
10993210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer}
11093210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer
11193210e847a1496b24cef881723e57c489082dcfeMichael J. Spencerstatic void dumpStream(yaml::Stream &stream) {
11293210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  for (yaml::document_iterator di = stream.begin(), de = stream.end(); di != de;
11393210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer       ++di) {
11493210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    outs() << "%YAML 1.2\n"
11593210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer           << "---\n";
11693210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    yaml::Node *n = di->getRoot();
11793210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    if (n)
11893210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer      dumpNode(n);
11993210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    else
12093210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer      break;
12193210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    outs() << "\n...\n";
12293210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  }
12393210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer}
12493210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer
12593210e847a1496b24cef881723e57c489082dcfeMichael J. Spencerstatic void benchmark( llvm::TimerGroup &Group
12693210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer                     , llvm::StringRef Name
12793210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer                     , llvm::StringRef JSONText) {
12893210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  llvm::Timer BaseLine((Name + ": Loop").str(), Group);
12993210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  BaseLine.startTimer();
13093210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  char C = 0;
13193210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  for (llvm::StringRef::iterator I = JSONText.begin(),
13293210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer                                 E = JSONText.end();
13393210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer       I != E; ++I) { C += *I; }
13493210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  BaseLine.stopTimer();
13593210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  volatile char DontOptimizeOut = C; (void)DontOptimizeOut;
13693210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer
13793210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  llvm::Timer Tokenizing((Name + ": Tokenizing").str(), Group);
13893210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  Tokenizing.startTimer();
13993210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  {
14093210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    yaml::scanTokens(JSONText);
14193210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  }
14293210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  Tokenizing.stopTimer();
14393210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer
14493210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  llvm::Timer Parsing((Name + ": Parsing").str(), Group);
14593210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  Parsing.startTimer();
14693210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  {
14793210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    llvm::SourceMgr SM;
14893210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    llvm::yaml::Stream stream(JSONText, SM);
14993210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    stream.skip();
15093210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  }
15193210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  Parsing.stopTimer();
15293210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer}
15393210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer
15493210e847a1496b24cef881723e57c489082dcfeMichael J. Spencerstatic std::string createJSONText(size_t MemoryMB, unsigned ValueSize) {
15593210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  std::string JSONText;
15693210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  llvm::raw_string_ostream Stream(JSONText);
15793210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  Stream << "[\n";
15893210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  size_t MemoryBytes = MemoryMB * 1024 * 1024;
15993210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  while (JSONText.size() < MemoryBytes) {
16093210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    Stream << " {\n"
16193210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer           << "  \"key1\": \"" << std::string(ValueSize, '*') << "\",\n"
16293210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer           << "  \"key2\": \"" << std::string(ValueSize, '*') << "\",\n"
16393210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer           << "  \"key3\": \"" << std::string(ValueSize, '*') << "\"\n"
16493210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer           << " }";
16593210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    Stream.flush();
16693210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    if (JSONText.size() < MemoryBytes) Stream << ",";
16793210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    Stream << "\n";
16893210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  }
16993210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  Stream << "]\n";
17093210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  Stream.flush();
17193210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  return JSONText;
17293210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer}
17393210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer
17493210e847a1496b24cef881723e57c489082dcfeMichael J. Spencerint main(int argc, char **argv) {
17593210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  llvm::cl::ParseCommandLineOptions(argc, argv);
17693210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  if (Input.getNumOccurrences()) {
17793210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    OwningPtr<MemoryBuffer> Buf;
17893210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    if (MemoryBuffer::getFileOrSTDIN(Input, Buf))
17993210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer      return 1;
18093210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer
18193210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    llvm::SourceMgr sm;
18293210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    if (DumpTokens) {
18393210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer      yaml::dumpTokens(Buf->getBuffer(), outs());
18493210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    }
18593210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer
18693210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    if (DumpCanonical) {
18793210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer      yaml::Stream stream(Buf->getBuffer(), sm);
18893210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer      dumpStream(stream);
18993210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    }
19093210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  }
19193210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer
19293210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  if (Verify) {
19393210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    llvm::TimerGroup Group("YAML parser benchmark");
19493210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    benchmark(Group, "Fast", createJSONText(10, 500));
19593210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  } else if (!DumpCanonical && !DumpTokens) {
19693210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    llvm::TimerGroup Group("YAML parser benchmark");
19793210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    benchmark(Group, "Small Values", createJSONText(MemoryLimitMB, 5));
19893210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    benchmark(Group, "Medium Values", createJSONText(MemoryLimitMB, 500));
19993210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer    benchmark(Group, "Large Values", createJSONText(MemoryLimitMB, 50000));
20093210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  }
20193210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer
20293210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer  return 0;
20393210e847a1496b24cef881723e57c489082dcfeMichael J. Spencer}
204