xref: /aosp_15_r20/external/llvm/utils/yaml-bench/YAMLBench.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
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