blob: 8bd1ea17ea8e2d7e789180e2ea8289eb9cd41747 [file] [log] [blame]
Michael J. Spencer22120c42012-04-03 23:09:22 +00001//===- YAMLBench - Benchmark the YAMLParser implementation ----------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
David Blaikie2a528822014-04-05 20:28:13 +000010// This program executes the YAMLParser on differently sized YAML texts and
Michael J. Spencer22120c42012-04-03 23:09:22 +000011// outputs the run time.
12//
13//===----------------------------------------------------------------------===//
14
15
16#include "llvm/ADT/SmallString.h"
17#include "llvm/Support/Casting.h"
18#include "llvm/Support/CommandLine.h"
19#include "llvm/Support/MemoryBuffer.h"
Michael J. Spencer22120c42012-04-03 23:09:22 +000020#include "llvm/Support/SourceMgr.h"
Michael J. Spencer22120c42012-04-03 23:09:22 +000021#include "llvm/Support/Timer.h"
22#include "llvm/Support/YAMLParser.h"
Chandler Carruth91d19d82012-12-04 10:37:14 +000023#include "llvm/Support/raw_ostream.h"
Rafael Espindolaa6e9c3e2014-06-12 17:38:55 +000024#include <system_error>
Michael J. Spencer22120c42012-04-03 23:09:22 +000025
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
55struct indent {
56 unsigned distance;
57 indent(unsigned d) : distance(d) {}
58};
59
60static raw_ostream &operator <<(raw_ostream &os, const indent &in) {
61 for (unsigned i = 0; i < in.distance; ++i)
62 os << " ";
63 return os;
64}
65
Michael J. Spencerc064a9a2013-10-18 22:38:04 +000066/// \brief Pretty print a tag by replacing tag:yaml.org,2002: with !!.
67static std::string prettyTag(yaml::Node *N) {
68 std::string Tag = N->getVerbatimTag();
69 if (StringRef(Tag).startswith("tag:yaml.org,2002:")) {
70 std::string Ret = "!!";
71 Ret += StringRef(Tag).substr(18);
Chandler Carruth002da5d2014-03-02 04:08:41 +000072 return std::move(Ret);
Michael J. Spencerc064a9a2013-10-18 22:38:04 +000073 }
74 std::string Ret = "!<";
75 Ret += Tag;
76 Ret += ">";
77 return Ret;
78}
79
Michael J. Spencer22120c42012-04-03 23:09:22 +000080static void dumpNode( yaml::Node *n
81 , unsigned Indent = 0
82 , bool SuppressFirstIndent = false) {
83 if (!n)
84 return;
85 if (!SuppressFirstIndent)
86 outs() << indent(Indent);
87 StringRef Anchor = n->getAnchor();
88 if (!Anchor.empty())
89 outs() << "&" << Anchor << " ";
90 if (yaml::ScalarNode *sn = dyn_cast<yaml::ScalarNode>(n)) {
91 SmallString<32> Storage;
92 StringRef Val = sn->getValue(Storage);
Michael J. Spencerc064a9a2013-10-18 22:38:04 +000093 outs() << prettyTag(n) << " \"" << yaml::escape(Val) << "\"";
Michael J. Spencer22120c42012-04-03 23:09:22 +000094 } else if (yaml::SequenceNode *sn = dyn_cast<yaml::SequenceNode>(n)) {
Michael J. Spencerc064a9a2013-10-18 22:38:04 +000095 outs() << prettyTag(n) << " [\n";
Michael J. Spencer22120c42012-04-03 23:09:22 +000096 ++Indent;
97 for (yaml::SequenceNode::iterator i = sn->begin(), e = sn->end();
98 i != e; ++i) {
99 dumpNode(i, Indent);
100 outs() << ",\n";
101 }
102 --Indent;
103 outs() << indent(Indent) << "]";
104 } else if (yaml::MappingNode *mn = dyn_cast<yaml::MappingNode>(n)) {
Michael J. Spencerc064a9a2013-10-18 22:38:04 +0000105 outs() << prettyTag(n) << " {\n";
Michael J. Spencer22120c42012-04-03 23:09:22 +0000106 ++Indent;
107 for (yaml::MappingNode::iterator i = mn->begin(), e = mn->end();
108 i != e; ++i) {
109 outs() << indent(Indent) << "? ";
110 dumpNode(i->getKey(), Indent, true);
111 outs() << "\n";
112 outs() << indent(Indent) << ": ";
113 dumpNode(i->getValue(), Indent, true);
114 outs() << ",\n";
115 }
116 --Indent;
117 outs() << indent(Indent) << "}";
118 } else if (yaml::AliasNode *an = dyn_cast<yaml::AliasNode>(n)){
119 outs() << "*" << an->getName();
120 } else if (dyn_cast<yaml::NullNode>(n)) {
Michael J. Spencerc064a9a2013-10-18 22:38:04 +0000121 outs() << prettyTag(n) << " null";
Michael J. Spencer22120c42012-04-03 23:09:22 +0000122 }
123}
124
125static void dumpStream(yaml::Stream &stream) {
126 for (yaml::document_iterator di = stream.begin(), de = stream.end(); di != de;
127 ++di) {
128 outs() << "%YAML 1.2\n"
129 << "---\n";
130 yaml::Node *n = di->getRoot();
131 if (n)
132 dumpNode(n);
133 else
134 break;
135 outs() << "\n...\n";
136 }
137}
138
139static void benchmark( llvm::TimerGroup &Group
140 , llvm::StringRef Name
141 , llvm::StringRef JSONText) {
142 llvm::Timer BaseLine((Name + ": Loop").str(), Group);
143 BaseLine.startTimer();
144 char C = 0;
145 for (llvm::StringRef::iterator I = JSONText.begin(),
146 E = JSONText.end();
147 I != E; ++I) { C += *I; }
148 BaseLine.stopTimer();
149 volatile char DontOptimizeOut = C; (void)DontOptimizeOut;
150
151 llvm::Timer Tokenizing((Name + ": Tokenizing").str(), Group);
152 Tokenizing.startTimer();
153 {
154 yaml::scanTokens(JSONText);
155 }
156 Tokenizing.stopTimer();
157
158 llvm::Timer Parsing((Name + ": Parsing").str(), Group);
159 Parsing.startTimer();
160 {
161 llvm::SourceMgr SM;
162 llvm::yaml::Stream stream(JSONText, SM);
163 stream.skip();
164 }
165 Parsing.stopTimer();
166}
167
168static std::string createJSONText(size_t MemoryMB, unsigned ValueSize) {
Alp Tokere69170a2014-06-26 22:52:05 +0000169 std::string JSONText;
170 llvm::raw_string_ostream Stream(JSONText);
171 Stream << "[\n";
Michael J. Spencer22120c42012-04-03 23:09:22 +0000172 size_t MemoryBytes = MemoryMB * 1024 * 1024;
Alp Tokere69170a2014-06-26 22:52:05 +0000173 while (JSONText.size() < MemoryBytes) {
174 Stream << " {\n"
175 << " \"key1\": \"" << std::string(ValueSize, '*') << "\",\n"
176 << " \"key2\": \"" << std::string(ValueSize, '*') << "\",\n"
177 << " \"key3\": \"" << std::string(ValueSize, '*') << "\"\n"
178 << " }";
179 Stream.flush();
180 if (JSONText.size() < MemoryBytes) Stream << ",";
181 Stream << "\n";
Michael J. Spencer22120c42012-04-03 23:09:22 +0000182 }
Alp Tokere69170a2014-06-26 22:52:05 +0000183 Stream << "]\n";
184 Stream.flush();
185 return JSONText;
Michael J. Spencer22120c42012-04-03 23:09:22 +0000186}
187
188int main(int argc, char **argv) {
189 llvm::cl::ParseCommandLineOptions(argc, argv);
190 if (Input.getNumOccurrences()) {
Rafael Espindolaadf21f22014-07-06 17:43:13 +0000191 ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr =
192 MemoryBuffer::getFileOrSTDIN(Input);
193 if (!BufOrErr)
Michael J. Spencer22120c42012-04-03 23:09:22 +0000194 return 1;
Rafael Espindola3f6481d2014-08-01 14:31:55 +0000195 MemoryBuffer &Buf = *BufOrErr.get();
Michael J. Spencer22120c42012-04-03 23:09:22 +0000196
197 llvm::SourceMgr sm;
198 if (DumpTokens) {
Rafael Espindola3f6481d2014-08-01 14:31:55 +0000199 yaml::dumpTokens(Buf.getBuffer(), outs());
Michael J. Spencer22120c42012-04-03 23:09:22 +0000200 }
201
202 if (DumpCanonical) {
Rafael Espindola3f6481d2014-08-01 14:31:55 +0000203 yaml::Stream stream(Buf.getBuffer(), sm);
Michael J. Spencer22120c42012-04-03 23:09:22 +0000204 dumpStream(stream);
205 }
206 }
207
208 if (Verify) {
209 llvm::TimerGroup Group("YAML parser benchmark");
210 benchmark(Group, "Fast", createJSONText(10, 500));
211 } else if (!DumpCanonical && !DumpTokens) {
212 llvm::TimerGroup Group("YAML parser benchmark");
213 benchmark(Group, "Small Values", createJSONText(MemoryLimitMB, 5));
214 benchmark(Group, "Medium Values", createJSONText(MemoryLimitMB, 500));
215 benchmark(Group, "Large Values", createJSONText(MemoryLimitMB, 50000));
216 }
217
218 return 0;
219}