blob: bd5aa152dffdd20aa762252a70afcb73445e7741 [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"
Alex Lorenze4bcfbf2015-05-07 18:08:46 +000022#include "llvm/Support/Process.h"
Michael J. Spencer22120c42012-04-03 23:09:22 +000023#include "llvm/Support/YAMLParser.h"
Chandler Carruth91d19d82012-12-04 10:37:14 +000024#include "llvm/Support/raw_ostream.h"
Rafael Espindolaa6e9c3e2014-06-12 17:38:55 +000025#include <system_error>
Michael J. Spencer22120c42012-04-03 23:09:22 +000026
27using namespace llvm;
28
29static cl::opt<bool>
30 DumpTokens( "tokens"
31 , cl::desc("Print the tokenization of the file.")
32 , cl::init(false)
33 );
34
35static cl::opt<bool>
36 DumpCanonical( "canonical"
37 , cl::desc("Print the canonical YAML for this file.")
38 , cl::init(false)
39 );
40
41static cl::opt<std::string>
42 Input(cl::Positional, cl::desc("<input>"));
43
44static cl::opt<bool>
45 Verify( "verify"
46 , cl::desc(
47 "Run a quick verification useful for regression testing")
48 , cl::init(false)
49 );
50
51static cl::opt<unsigned>
52 MemoryLimitMB("memory-limit", cl::desc(
53 "Do not use more megabytes of memory"),
54 cl::init(1000));
55
Alex Lorenze4bcfbf2015-05-07 18:08:46 +000056cl::opt<cl::boolOrDefault>
57 UseColor("use-color", cl::desc("Emit colored output (default=autodetect)"),
58 cl::init(cl::BOU_UNSET));
59
Michael J. Spencer22120c42012-04-03 23:09:22 +000060struct indent {
61 unsigned distance;
62 indent(unsigned d) : distance(d) {}
63};
64
65static raw_ostream &operator <<(raw_ostream &os, const indent &in) {
66 for (unsigned i = 0; i < in.distance; ++i)
67 os << " ";
68 return os;
69}
70
Michael J. Spencerc064a9a2013-10-18 22:38:04 +000071/// \brief Pretty print a tag by replacing tag:yaml.org,2002: with !!.
72static std::string prettyTag(yaml::Node *N) {
73 std::string Tag = N->getVerbatimTag();
74 if (StringRef(Tag).startswith("tag:yaml.org,2002:")) {
75 std::string Ret = "!!";
76 Ret += StringRef(Tag).substr(18);
Benjamin Kramer548e8a42015-05-01 15:16:11 +000077 return Ret;
Michael J. Spencerc064a9a2013-10-18 22:38:04 +000078 }
79 std::string Ret = "!<";
80 Ret += Tag;
81 Ret += ">";
82 return Ret;
83}
84
Michael J. Spencer22120c42012-04-03 23:09:22 +000085static void dumpNode( yaml::Node *n
86 , unsigned Indent = 0
87 , bool SuppressFirstIndent = false) {
88 if (!n)
89 return;
90 if (!SuppressFirstIndent)
91 outs() << indent(Indent);
92 StringRef Anchor = n->getAnchor();
93 if (!Anchor.empty())
94 outs() << "&" << Anchor << " ";
95 if (yaml::ScalarNode *sn = dyn_cast<yaml::ScalarNode>(n)) {
96 SmallString<32> Storage;
97 StringRef Val = sn->getValue(Storage);
Michael J. Spencerc064a9a2013-10-18 22:38:04 +000098 outs() << prettyTag(n) << " \"" << yaml::escape(Val) << "\"";
Michael J. Spencer22120c42012-04-03 23:09:22 +000099 } else if (yaml::SequenceNode *sn = dyn_cast<yaml::SequenceNode>(n)) {
Michael J. Spencerc064a9a2013-10-18 22:38:04 +0000100 outs() << prettyTag(n) << " [\n";
Michael J. Spencer22120c42012-04-03 23:09:22 +0000101 ++Indent;
102 for (yaml::SequenceNode::iterator i = sn->begin(), e = sn->end();
103 i != e; ++i) {
104 dumpNode(i, Indent);
105 outs() << ",\n";
106 }
107 --Indent;
108 outs() << indent(Indent) << "]";
109 } else if (yaml::MappingNode *mn = dyn_cast<yaml::MappingNode>(n)) {
Michael J. Spencerc064a9a2013-10-18 22:38:04 +0000110 outs() << prettyTag(n) << " {\n";
Michael J. Spencer22120c42012-04-03 23:09:22 +0000111 ++Indent;
112 for (yaml::MappingNode::iterator i = mn->begin(), e = mn->end();
113 i != e; ++i) {
114 outs() << indent(Indent) << "? ";
115 dumpNode(i->getKey(), Indent, true);
116 outs() << "\n";
117 outs() << indent(Indent) << ": ";
118 dumpNode(i->getValue(), Indent, true);
119 outs() << ",\n";
120 }
121 --Indent;
122 outs() << indent(Indent) << "}";
123 } else if (yaml::AliasNode *an = dyn_cast<yaml::AliasNode>(n)){
124 outs() << "*" << an->getName();
Benjamin Kramer619c4e52015-04-10 11:24:51 +0000125 } else if (isa<yaml::NullNode>(n)) {
Michael J. Spencerc064a9a2013-10-18 22:38:04 +0000126 outs() << prettyTag(n) << " null";
Michael J. Spencer22120c42012-04-03 23:09:22 +0000127 }
128}
129
130static void dumpStream(yaml::Stream &stream) {
131 for (yaml::document_iterator di = stream.begin(), de = stream.end(); di != de;
132 ++di) {
133 outs() << "%YAML 1.2\n"
134 << "---\n";
135 yaml::Node *n = di->getRoot();
136 if (n)
137 dumpNode(n);
138 else
139 break;
140 outs() << "\n...\n";
141 }
142}
143
144static void benchmark( llvm::TimerGroup &Group
145 , llvm::StringRef Name
146 , llvm::StringRef JSONText) {
147 llvm::Timer BaseLine((Name + ": Loop").str(), Group);
148 BaseLine.startTimer();
149 char C = 0;
150 for (llvm::StringRef::iterator I = JSONText.begin(),
151 E = JSONText.end();
152 I != E; ++I) { C += *I; }
153 BaseLine.stopTimer();
154 volatile char DontOptimizeOut = C; (void)DontOptimizeOut;
155
156 llvm::Timer Tokenizing((Name + ": Tokenizing").str(), Group);
157 Tokenizing.startTimer();
158 {
159 yaml::scanTokens(JSONText);
160 }
161 Tokenizing.stopTimer();
162
163 llvm::Timer Parsing((Name + ": Parsing").str(), Group);
164 Parsing.startTimer();
165 {
166 llvm::SourceMgr SM;
167 llvm::yaml::Stream stream(JSONText, SM);
168 stream.skip();
169 }
170 Parsing.stopTimer();
171}
172
173static std::string createJSONText(size_t MemoryMB, unsigned ValueSize) {
Alp Tokere69170a2014-06-26 22:52:05 +0000174 std::string JSONText;
175 llvm::raw_string_ostream Stream(JSONText);
176 Stream << "[\n";
Michael J. Spencer22120c42012-04-03 23:09:22 +0000177 size_t MemoryBytes = MemoryMB * 1024 * 1024;
Alp Tokere69170a2014-06-26 22:52:05 +0000178 while (JSONText.size() < MemoryBytes) {
179 Stream << " {\n"
180 << " \"key1\": \"" << std::string(ValueSize, '*') << "\",\n"
181 << " \"key2\": \"" << std::string(ValueSize, '*') << "\",\n"
182 << " \"key3\": \"" << std::string(ValueSize, '*') << "\"\n"
183 << " }";
184 Stream.flush();
185 if (JSONText.size() < MemoryBytes) Stream << ",";
186 Stream << "\n";
Michael J. Spencer22120c42012-04-03 23:09:22 +0000187 }
Alp Tokere69170a2014-06-26 22:52:05 +0000188 Stream << "]\n";
189 Stream.flush();
190 return JSONText;
Michael J. Spencer22120c42012-04-03 23:09:22 +0000191}
192
193int main(int argc, char **argv) {
194 llvm::cl::ParseCommandLineOptions(argc, argv);
Alex Lorenze4bcfbf2015-05-07 18:08:46 +0000195 bool ShowColors = UseColor == cl::BOU_UNSET
196 ? sys::Process::StandardOutHasColors()
197 : UseColor == cl::BOU_TRUE;
Michael J. Spencer22120c42012-04-03 23:09:22 +0000198 if (Input.getNumOccurrences()) {
Rafael Espindolaadf21f22014-07-06 17:43:13 +0000199 ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr =
200 MemoryBuffer::getFileOrSTDIN(Input);
201 if (!BufOrErr)
Michael J. Spencer22120c42012-04-03 23:09:22 +0000202 return 1;
Rafael Espindola3f6481d2014-08-01 14:31:55 +0000203 MemoryBuffer &Buf = *BufOrErr.get();
Michael J. Spencer22120c42012-04-03 23:09:22 +0000204
205 llvm::SourceMgr sm;
206 if (DumpTokens) {
Rafael Espindola3f6481d2014-08-01 14:31:55 +0000207 yaml::dumpTokens(Buf.getBuffer(), outs());
Michael J. Spencer22120c42012-04-03 23:09:22 +0000208 }
209
210 if (DumpCanonical) {
Alex Lorenze4bcfbf2015-05-07 18:08:46 +0000211 yaml::Stream stream(Buf.getBuffer(), sm, ShowColors);
Michael J. Spencer22120c42012-04-03 23:09:22 +0000212 dumpStream(stream);
Alex Lorenze4bcfbf2015-05-07 18:08:46 +0000213 if (stream.failed())
214 return 1;
Michael J. Spencer22120c42012-04-03 23:09:22 +0000215 }
216 }
217
218 if (Verify) {
219 llvm::TimerGroup Group("YAML parser benchmark");
220 benchmark(Group, "Fast", createJSONText(10, 500));
221 } else if (!DumpCanonical && !DumpTokens) {
222 llvm::TimerGroup Group("YAML parser benchmark");
223 benchmark(Group, "Small Values", createJSONText(MemoryLimitMB, 5));
224 benchmark(Group, "Medium Values", createJSONText(MemoryLimitMB, 500));
225 benchmark(Group, "Large Values", createJSONText(MemoryLimitMB, 50000));
226 }
227
228 return 0;
229}