1*9880d681SAndroid Build Coastguard Worker //===- YAMLBench - Benchmark the YAMLParser implementation ----------------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // This program executes the YAMLParser on differently sized YAML texts and
11*9880d681SAndroid Build Coastguard Worker // outputs the run time.
12*9880d681SAndroid Build Coastguard Worker //
13*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
14*9880d681SAndroid Build Coastguard Worker
15*9880d681SAndroid Build Coastguard Worker
16*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/SmallString.h"
17*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Casting.h"
18*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/CommandLine.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/MemoryBuffer.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/SourceMgr.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Timer.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Process.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/YAMLParser.h"
24*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h"
25*9880d681SAndroid Build Coastguard Worker #include <system_error>
26*9880d681SAndroid Build Coastguard Worker
27*9880d681SAndroid Build Coastguard Worker using namespace llvm;
28*9880d681SAndroid Build Coastguard Worker
29*9880d681SAndroid Build Coastguard Worker static cl::opt<bool>
30*9880d681SAndroid Build Coastguard Worker DumpTokens( "tokens"
31*9880d681SAndroid Build Coastguard Worker , cl::desc("Print the tokenization of the file.")
32*9880d681SAndroid Build Coastguard Worker , cl::init(false)
33*9880d681SAndroid Build Coastguard Worker );
34*9880d681SAndroid Build Coastguard Worker
35*9880d681SAndroid Build Coastguard Worker static cl::opt<bool>
36*9880d681SAndroid Build Coastguard Worker DumpCanonical( "canonical"
37*9880d681SAndroid Build Coastguard Worker , cl::desc("Print the canonical YAML for this file.")
38*9880d681SAndroid Build Coastguard Worker , cl::init(false)
39*9880d681SAndroid Build Coastguard Worker );
40*9880d681SAndroid Build Coastguard Worker
41*9880d681SAndroid Build Coastguard Worker static cl::opt<std::string>
42*9880d681SAndroid Build Coastguard Worker Input(cl::Positional, cl::desc("<input>"));
43*9880d681SAndroid Build Coastguard Worker
44*9880d681SAndroid Build Coastguard Worker static cl::opt<bool>
45*9880d681SAndroid Build Coastguard Worker Verify( "verify"
46*9880d681SAndroid Build Coastguard Worker , cl::desc(
47*9880d681SAndroid Build Coastguard Worker "Run a quick verification useful for regression testing")
48*9880d681SAndroid Build Coastguard Worker , cl::init(false)
49*9880d681SAndroid Build Coastguard Worker );
50*9880d681SAndroid Build Coastguard Worker
51*9880d681SAndroid Build Coastguard Worker static cl::opt<unsigned>
52*9880d681SAndroid Build Coastguard Worker MemoryLimitMB("memory-limit", cl::desc(
53*9880d681SAndroid Build Coastguard Worker "Do not use more megabytes of memory"),
54*9880d681SAndroid Build Coastguard Worker cl::init(1000));
55*9880d681SAndroid Build Coastguard Worker
56*9880d681SAndroid Build Coastguard Worker cl::opt<cl::boolOrDefault>
57*9880d681SAndroid Build Coastguard Worker UseColor("use-color", cl::desc("Emit colored output (default=autodetect)"),
58*9880d681SAndroid Build Coastguard Worker cl::init(cl::BOU_UNSET));
59*9880d681SAndroid Build Coastguard Worker
60*9880d681SAndroid Build Coastguard Worker struct indent {
61*9880d681SAndroid Build Coastguard Worker unsigned distance;
indentindent62*9880d681SAndroid Build Coastguard Worker indent(unsigned d) : distance(d) {}
63*9880d681SAndroid Build Coastguard Worker };
64*9880d681SAndroid Build Coastguard Worker
operator <<(raw_ostream & os,const indent & in)65*9880d681SAndroid Build Coastguard Worker static raw_ostream &operator <<(raw_ostream &os, const indent &in) {
66*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0; i < in.distance; ++i)
67*9880d681SAndroid Build Coastguard Worker os << " ";
68*9880d681SAndroid Build Coastguard Worker return os;
69*9880d681SAndroid Build Coastguard Worker }
70*9880d681SAndroid Build Coastguard Worker
71*9880d681SAndroid Build Coastguard Worker /// \brief Pretty print a tag by replacing tag:yaml.org,2002: with !!.
prettyTag(yaml::Node * N)72*9880d681SAndroid Build Coastguard Worker static std::string prettyTag(yaml::Node *N) {
73*9880d681SAndroid Build Coastguard Worker std::string Tag = N->getVerbatimTag();
74*9880d681SAndroid Build Coastguard Worker if (StringRef(Tag).startswith("tag:yaml.org,2002:")) {
75*9880d681SAndroid Build Coastguard Worker std::string Ret = "!!";
76*9880d681SAndroid Build Coastguard Worker Ret += StringRef(Tag).substr(18);
77*9880d681SAndroid Build Coastguard Worker return Ret;
78*9880d681SAndroid Build Coastguard Worker }
79*9880d681SAndroid Build Coastguard Worker std::string Ret = "!<";
80*9880d681SAndroid Build Coastguard Worker Ret += Tag;
81*9880d681SAndroid Build Coastguard Worker Ret += ">";
82*9880d681SAndroid Build Coastguard Worker return Ret;
83*9880d681SAndroid Build Coastguard Worker }
84*9880d681SAndroid Build Coastguard Worker
dumpNode(yaml::Node * n,unsigned Indent=0,bool SuppressFirstIndent=false)85*9880d681SAndroid Build Coastguard Worker static void dumpNode( yaml::Node *n
86*9880d681SAndroid Build Coastguard Worker , unsigned Indent = 0
87*9880d681SAndroid Build Coastguard Worker , bool SuppressFirstIndent = false) {
88*9880d681SAndroid Build Coastguard Worker if (!n)
89*9880d681SAndroid Build Coastguard Worker return;
90*9880d681SAndroid Build Coastguard Worker if (!SuppressFirstIndent)
91*9880d681SAndroid Build Coastguard Worker outs() << indent(Indent);
92*9880d681SAndroid Build Coastguard Worker StringRef Anchor = n->getAnchor();
93*9880d681SAndroid Build Coastguard Worker if (!Anchor.empty())
94*9880d681SAndroid Build Coastguard Worker outs() << "&" << Anchor << " ";
95*9880d681SAndroid Build Coastguard Worker if (yaml::ScalarNode *sn = dyn_cast<yaml::ScalarNode>(n)) {
96*9880d681SAndroid Build Coastguard Worker SmallString<32> Storage;
97*9880d681SAndroid Build Coastguard Worker StringRef Val = sn->getValue(Storage);
98*9880d681SAndroid Build Coastguard Worker outs() << prettyTag(n) << " \"" << yaml::escape(Val) << "\"";
99*9880d681SAndroid Build Coastguard Worker } else if (yaml::BlockScalarNode *BN = dyn_cast<yaml::BlockScalarNode>(n)) {
100*9880d681SAndroid Build Coastguard Worker outs() << prettyTag(n) << " \"" << yaml::escape(BN->getValue()) << "\"";
101*9880d681SAndroid Build Coastguard Worker } else if (yaml::SequenceNode *sn = dyn_cast<yaml::SequenceNode>(n)) {
102*9880d681SAndroid Build Coastguard Worker outs() << prettyTag(n) << " [\n";
103*9880d681SAndroid Build Coastguard Worker ++Indent;
104*9880d681SAndroid Build Coastguard Worker for (yaml::SequenceNode::iterator i = sn->begin(), e = sn->end();
105*9880d681SAndroid Build Coastguard Worker i != e; ++i) {
106*9880d681SAndroid Build Coastguard Worker dumpNode(i, Indent);
107*9880d681SAndroid Build Coastguard Worker outs() << ",\n";
108*9880d681SAndroid Build Coastguard Worker }
109*9880d681SAndroid Build Coastguard Worker --Indent;
110*9880d681SAndroid Build Coastguard Worker outs() << indent(Indent) << "]";
111*9880d681SAndroid Build Coastguard Worker } else if (yaml::MappingNode *mn = dyn_cast<yaml::MappingNode>(n)) {
112*9880d681SAndroid Build Coastguard Worker outs() << prettyTag(n) << " {\n";
113*9880d681SAndroid Build Coastguard Worker ++Indent;
114*9880d681SAndroid Build Coastguard Worker for (yaml::MappingNode::iterator i = mn->begin(), e = mn->end();
115*9880d681SAndroid Build Coastguard Worker i != e; ++i) {
116*9880d681SAndroid Build Coastguard Worker outs() << indent(Indent) << "? ";
117*9880d681SAndroid Build Coastguard Worker dumpNode(i->getKey(), Indent, true);
118*9880d681SAndroid Build Coastguard Worker outs() << "\n";
119*9880d681SAndroid Build Coastguard Worker outs() << indent(Indent) << ": ";
120*9880d681SAndroid Build Coastguard Worker dumpNode(i->getValue(), Indent, true);
121*9880d681SAndroid Build Coastguard Worker outs() << ",\n";
122*9880d681SAndroid Build Coastguard Worker }
123*9880d681SAndroid Build Coastguard Worker --Indent;
124*9880d681SAndroid Build Coastguard Worker outs() << indent(Indent) << "}";
125*9880d681SAndroid Build Coastguard Worker } else if (yaml::AliasNode *an = dyn_cast<yaml::AliasNode>(n)){
126*9880d681SAndroid Build Coastguard Worker outs() << "*" << an->getName();
127*9880d681SAndroid Build Coastguard Worker } else if (isa<yaml::NullNode>(n)) {
128*9880d681SAndroid Build Coastguard Worker outs() << prettyTag(n) << " null";
129*9880d681SAndroid Build Coastguard Worker }
130*9880d681SAndroid Build Coastguard Worker }
131*9880d681SAndroid Build Coastguard Worker
dumpStream(yaml::Stream & stream)132*9880d681SAndroid Build Coastguard Worker static void dumpStream(yaml::Stream &stream) {
133*9880d681SAndroid Build Coastguard Worker for (yaml::document_iterator di = stream.begin(), de = stream.end(); di != de;
134*9880d681SAndroid Build Coastguard Worker ++di) {
135*9880d681SAndroid Build Coastguard Worker outs() << "%YAML 1.2\n"
136*9880d681SAndroid Build Coastguard Worker << "---\n";
137*9880d681SAndroid Build Coastguard Worker yaml::Node *n = di->getRoot();
138*9880d681SAndroid Build Coastguard Worker if (n)
139*9880d681SAndroid Build Coastguard Worker dumpNode(n);
140*9880d681SAndroid Build Coastguard Worker else
141*9880d681SAndroid Build Coastguard Worker break;
142*9880d681SAndroid Build Coastguard Worker outs() << "\n...\n";
143*9880d681SAndroid Build Coastguard Worker }
144*9880d681SAndroid Build Coastguard Worker }
145*9880d681SAndroid Build Coastguard Worker
benchmark(llvm::TimerGroup & Group,llvm::StringRef Name,llvm::StringRef JSONText)146*9880d681SAndroid Build Coastguard Worker static void benchmark( llvm::TimerGroup &Group
147*9880d681SAndroid Build Coastguard Worker , llvm::StringRef Name
148*9880d681SAndroid Build Coastguard Worker , llvm::StringRef JSONText) {
149*9880d681SAndroid Build Coastguard Worker llvm::Timer BaseLine((Name + ": Loop").str(), Group);
150*9880d681SAndroid Build Coastguard Worker BaseLine.startTimer();
151*9880d681SAndroid Build Coastguard Worker char C = 0;
152*9880d681SAndroid Build Coastguard Worker for (llvm::StringRef::iterator I = JSONText.begin(),
153*9880d681SAndroid Build Coastguard Worker E = JSONText.end();
154*9880d681SAndroid Build Coastguard Worker I != E; ++I) { C += *I; }
155*9880d681SAndroid Build Coastguard Worker BaseLine.stopTimer();
156*9880d681SAndroid Build Coastguard Worker volatile char DontOptimizeOut = C; (void)DontOptimizeOut;
157*9880d681SAndroid Build Coastguard Worker
158*9880d681SAndroid Build Coastguard Worker llvm::Timer Tokenizing((Name + ": Tokenizing").str(), Group);
159*9880d681SAndroid Build Coastguard Worker Tokenizing.startTimer();
160*9880d681SAndroid Build Coastguard Worker {
161*9880d681SAndroid Build Coastguard Worker yaml::scanTokens(JSONText);
162*9880d681SAndroid Build Coastguard Worker }
163*9880d681SAndroid Build Coastguard Worker Tokenizing.stopTimer();
164*9880d681SAndroid Build Coastguard Worker
165*9880d681SAndroid Build Coastguard Worker llvm::Timer Parsing((Name + ": Parsing").str(), Group);
166*9880d681SAndroid Build Coastguard Worker Parsing.startTimer();
167*9880d681SAndroid Build Coastguard Worker {
168*9880d681SAndroid Build Coastguard Worker llvm::SourceMgr SM;
169*9880d681SAndroid Build Coastguard Worker llvm::yaml::Stream stream(JSONText, SM);
170*9880d681SAndroid Build Coastguard Worker stream.skip();
171*9880d681SAndroid Build Coastguard Worker }
172*9880d681SAndroid Build Coastguard Worker Parsing.stopTimer();
173*9880d681SAndroid Build Coastguard Worker }
174*9880d681SAndroid Build Coastguard Worker
createJSONText(size_t MemoryMB,unsigned ValueSize)175*9880d681SAndroid Build Coastguard Worker static std::string createJSONText(size_t MemoryMB, unsigned ValueSize) {
176*9880d681SAndroid Build Coastguard Worker std::string JSONText;
177*9880d681SAndroid Build Coastguard Worker llvm::raw_string_ostream Stream(JSONText);
178*9880d681SAndroid Build Coastguard Worker Stream << "[\n";
179*9880d681SAndroid Build Coastguard Worker size_t MemoryBytes = MemoryMB * 1024 * 1024;
180*9880d681SAndroid Build Coastguard Worker while (JSONText.size() < MemoryBytes) {
181*9880d681SAndroid Build Coastguard Worker Stream << " {\n"
182*9880d681SAndroid Build Coastguard Worker << " \"key1\": \"" << std::string(ValueSize, '*') << "\",\n"
183*9880d681SAndroid Build Coastguard Worker << " \"key2\": \"" << std::string(ValueSize, '*') << "\",\n"
184*9880d681SAndroid Build Coastguard Worker << " \"key3\": \"" << std::string(ValueSize, '*') << "\"\n"
185*9880d681SAndroid Build Coastguard Worker << " }";
186*9880d681SAndroid Build Coastguard Worker Stream.flush();
187*9880d681SAndroid Build Coastguard Worker if (JSONText.size() < MemoryBytes) Stream << ",";
188*9880d681SAndroid Build Coastguard Worker Stream << "\n";
189*9880d681SAndroid Build Coastguard Worker }
190*9880d681SAndroid Build Coastguard Worker Stream << "]\n";
191*9880d681SAndroid Build Coastguard Worker Stream.flush();
192*9880d681SAndroid Build Coastguard Worker return JSONText;
193*9880d681SAndroid Build Coastguard Worker }
194*9880d681SAndroid Build Coastguard Worker
main(int argc,char ** argv)195*9880d681SAndroid Build Coastguard Worker int main(int argc, char **argv) {
196*9880d681SAndroid Build Coastguard Worker llvm::cl::ParseCommandLineOptions(argc, argv);
197*9880d681SAndroid Build Coastguard Worker bool ShowColors = UseColor == cl::BOU_UNSET
198*9880d681SAndroid Build Coastguard Worker ? sys::Process::StandardOutHasColors()
199*9880d681SAndroid Build Coastguard Worker : UseColor == cl::BOU_TRUE;
200*9880d681SAndroid Build Coastguard Worker if (Input.getNumOccurrences()) {
201*9880d681SAndroid Build Coastguard Worker ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr =
202*9880d681SAndroid Build Coastguard Worker MemoryBuffer::getFileOrSTDIN(Input);
203*9880d681SAndroid Build Coastguard Worker if (!BufOrErr)
204*9880d681SAndroid Build Coastguard Worker return 1;
205*9880d681SAndroid Build Coastguard Worker MemoryBuffer &Buf = *BufOrErr.get();
206*9880d681SAndroid Build Coastguard Worker
207*9880d681SAndroid Build Coastguard Worker llvm::SourceMgr sm;
208*9880d681SAndroid Build Coastguard Worker if (DumpTokens) {
209*9880d681SAndroid Build Coastguard Worker yaml::dumpTokens(Buf.getBuffer(), outs());
210*9880d681SAndroid Build Coastguard Worker }
211*9880d681SAndroid Build Coastguard Worker
212*9880d681SAndroid Build Coastguard Worker if (DumpCanonical) {
213*9880d681SAndroid Build Coastguard Worker yaml::Stream stream(Buf.getBuffer(), sm, ShowColors);
214*9880d681SAndroid Build Coastguard Worker dumpStream(stream);
215*9880d681SAndroid Build Coastguard Worker if (stream.failed())
216*9880d681SAndroid Build Coastguard Worker return 1;
217*9880d681SAndroid Build Coastguard Worker }
218*9880d681SAndroid Build Coastguard Worker }
219*9880d681SAndroid Build Coastguard Worker
220*9880d681SAndroid Build Coastguard Worker if (Verify) {
221*9880d681SAndroid Build Coastguard Worker llvm::TimerGroup Group("YAML parser benchmark");
222*9880d681SAndroid Build Coastguard Worker benchmark(Group, "Fast", createJSONText(10, 500));
223*9880d681SAndroid Build Coastguard Worker } else if (!DumpCanonical && !DumpTokens) {
224*9880d681SAndroid Build Coastguard Worker llvm::TimerGroup Group("YAML parser benchmark");
225*9880d681SAndroid Build Coastguard Worker benchmark(Group, "Small Values", createJSONText(MemoryLimitMB, 5));
226*9880d681SAndroid Build Coastguard Worker benchmark(Group, "Medium Values", createJSONText(MemoryLimitMB, 500));
227*9880d681SAndroid Build Coastguard Worker benchmark(Group, "Large Values", createJSONText(MemoryLimitMB, 50000));
228*9880d681SAndroid Build Coastguard Worker }
229*9880d681SAndroid Build Coastguard Worker
230*9880d681SAndroid Build Coastguard Worker return 0;
231*9880d681SAndroid Build Coastguard Worker }
232