[llvm-exegesis] Fix missing std::move.
[llvm-complete.git] / utils / yaml-bench / YAMLBench.cpp
blob3688db6f438b7debfe129929b824ee5efbf56c88
1 //===- 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 //
10 // This program executes the YAMLParser on differently sized YAML texts and
11 // outputs the run time.
13 //===----------------------------------------------------------------------===//
16 #include "llvm/ADT/SmallString.h"
17 #include "llvm/Support/Casting.h"
18 #include "llvm/Support/CommandLine.h"
19 #include "llvm/Support/MemoryBuffer.h"
20 #include "llvm/Support/SourceMgr.h"
21 #include "llvm/Support/Timer.h"
22 #include "llvm/Support/Process.h"
23 #include "llvm/Support/YAMLParser.h"
24 #include "llvm/Support/raw_ostream.h"
25 #include <system_error>
27 using namespace llvm;
29 static cl::opt<bool>
30 DumpTokens( "tokens"
31 , cl::desc("Print the tokenization of the file.")
32 , cl::init(false)
35 static cl::opt<bool>
36 DumpCanonical( "canonical"
37 , cl::desc("Print the canonical YAML for this file.")
38 , cl::init(false)
41 static cl::opt<std::string>
42 Input(cl::Positional, cl::desc("<input>"));
44 static cl::opt<bool>
45 Verify( "verify"
46 , cl::desc(
47 "Run a quick verification useful for regression testing")
48 , cl::init(false)
51 static cl::opt<unsigned>
52 MemoryLimitMB("memory-limit", cl::desc(
53 "Do not use more megabytes of memory"),
54 cl::init(1000));
56 cl::opt<cl::boolOrDefault>
57 UseColor("use-color", cl::desc("Emit colored output (default=autodetect)"),
58 cl::init(cl::BOU_UNSET));
60 struct indent {
61 unsigned distance;
62 indent(unsigned d) : distance(d) {}
65 static raw_ostream &operator <<(raw_ostream &os, const indent &in) {
66 for (unsigned i = 0; i < in.distance; ++i)
67 os << " ";
68 return os;
71 /// Pretty print a tag by replacing tag:yaml.org,2002: with !!.
72 static 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);
77 return Ret;
79 std::string Ret = "!<";
80 Ret += Tag;
81 Ret += ">";
82 return Ret;
85 static 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);
98 outs() << prettyTag(n) << " \"" << yaml::escape(Val) << "\"";
99 } else if (yaml::BlockScalarNode *BN = dyn_cast<yaml::BlockScalarNode>(n)) {
100 outs() << prettyTag(n) << " \"" << yaml::escape(BN->getValue()) << "\"";
101 } else if (yaml::SequenceNode *sn = dyn_cast<yaml::SequenceNode>(n)) {
102 outs() << prettyTag(n) << " [\n";
103 ++Indent;
104 for (yaml::SequenceNode::iterator i = sn->begin(), e = sn->end();
105 i != e; ++i) {
106 dumpNode(i, Indent);
107 outs() << ",\n";
109 --Indent;
110 outs() << indent(Indent) << "]";
111 } else if (yaml::MappingNode *mn = dyn_cast<yaml::MappingNode>(n)) {
112 outs() << prettyTag(n) << " {\n";
113 ++Indent;
114 for (yaml::MappingNode::iterator i = mn->begin(), e = mn->end();
115 i != e; ++i) {
116 outs() << indent(Indent) << "? ";
117 dumpNode(i->getKey(), Indent, true);
118 outs() << "\n";
119 outs() << indent(Indent) << ": ";
120 dumpNode(i->getValue(), Indent, true);
121 outs() << ",\n";
123 --Indent;
124 outs() << indent(Indent) << "}";
125 } else if (yaml::AliasNode *an = dyn_cast<yaml::AliasNode>(n)){
126 outs() << "*" << an->getName();
127 } else if (isa<yaml::NullNode>(n)) {
128 outs() << prettyTag(n) << " null";
132 static void dumpStream(yaml::Stream &stream) {
133 for (yaml::document_iterator di = stream.begin(), de = stream.end(); di != de;
134 ++di) {
135 outs() << "%YAML 1.2\n"
136 << "---\n";
137 yaml::Node *n = di->getRoot();
138 if (n)
139 dumpNode(n);
140 else
141 break;
142 outs() << "\n...\n";
146 static void benchmark(llvm::TimerGroup &Group, llvm::StringRef Name,
147 llvm::StringRef Description, llvm::StringRef JSONText) {
148 llvm::Timer BaseLine((Name + ".loop").str(), (Description + ": Loop").str(),
149 Group);
150 BaseLine.startTimer();
151 char C = 0;
152 for (llvm::StringRef::iterator I = JSONText.begin(),
153 E = JSONText.end();
154 I != E; ++I) { C += *I; }
155 BaseLine.stopTimer();
156 volatile char DontOptimizeOut = C; (void)DontOptimizeOut;
158 llvm::Timer Tokenizing((Name + ".tokenizing").str(),
159 (Description + ": Tokenizing").str(), Group);
160 Tokenizing.startTimer();
162 yaml::scanTokens(JSONText);
164 Tokenizing.stopTimer();
166 llvm::Timer Parsing((Name + ".parsing").str(),
167 (Description + ": Parsing").str(), Group);
168 Parsing.startTimer();
170 llvm::SourceMgr SM;
171 llvm::yaml::Stream stream(JSONText, SM);
172 stream.skip();
174 Parsing.stopTimer();
177 static std::string createJSONText(size_t MemoryMB, unsigned ValueSize) {
178 std::string JSONText;
179 llvm::raw_string_ostream Stream(JSONText);
180 Stream << "[\n";
181 size_t MemoryBytes = MemoryMB * 1024 * 1024;
182 while (JSONText.size() < MemoryBytes) {
183 Stream << " {\n"
184 << " \"key1\": \"" << std::string(ValueSize, '*') << "\",\n"
185 << " \"key2\": \"" << std::string(ValueSize, '*') << "\",\n"
186 << " \"key3\": \"" << std::string(ValueSize, '*') << "\"\n"
187 << " }";
188 Stream.flush();
189 if (JSONText.size() < MemoryBytes) Stream << ",";
190 Stream << "\n";
192 Stream << "]\n";
193 Stream.flush();
194 return JSONText;
197 int main(int argc, char **argv) {
198 llvm::cl::ParseCommandLineOptions(argc, argv);
199 bool ShowColors = UseColor == cl::BOU_UNSET
200 ? sys::Process::StandardOutHasColors()
201 : UseColor == cl::BOU_TRUE;
202 if (Input.getNumOccurrences()) {
203 ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr =
204 MemoryBuffer::getFileOrSTDIN(Input);
205 if (!BufOrErr)
206 return 1;
207 MemoryBuffer &Buf = *BufOrErr.get();
209 llvm::SourceMgr sm;
210 if (DumpTokens) {
211 yaml::dumpTokens(Buf.getBuffer(), outs());
214 if (DumpCanonical) {
215 yaml::Stream stream(Buf.getBuffer(), sm, ShowColors);
216 dumpStream(stream);
217 if (stream.failed())
218 return 1;
222 if (Verify) {
223 llvm::TimerGroup Group("yaml", "YAML parser benchmark");
224 benchmark(Group, "Fast", "Fast", createJSONText(10, 500));
225 } else if (!DumpCanonical && !DumpTokens) {
226 llvm::TimerGroup Group("yaml", "YAML parser benchmark");
227 benchmark(Group, "Small", "Small Values", createJSONText(MemoryLimitMB, 5));
228 benchmark(Group, "Medium", "Medium Values",
229 createJSONText(MemoryLimitMB, 500));
230 benchmark(Group, "Large", "Large Values",
231 createJSONText(MemoryLimitMB, 50000));
234 return 0;