From 93210e847a1496b24cef881723e57c489082dcfe Mon Sep 17 00:00:00 2001 From: "Michael J. Spencer" Date: Tue, 3 Apr 2012 23:09:22 +0000 Subject: Add YAML parser to Support. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@153977 91177308-0d34-0410-b5e6-96231b3b80d8 --- utils/yaml-bench/CMakeLists.txt | 5 + utils/yaml-bench/Makefile | 20 ++++ utils/yaml-bench/YAMLBench.cpp | 203 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 228 insertions(+) create mode 100644 utils/yaml-bench/CMakeLists.txt create mode 100644 utils/yaml-bench/Makefile create mode 100644 utils/yaml-bench/YAMLBench.cpp (limited to 'utils/yaml-bench') diff --git a/utils/yaml-bench/CMakeLists.txt b/utils/yaml-bench/CMakeLists.txt new file mode 100644 index 00000000000..403182ceee2 --- /dev/null +++ b/utils/yaml-bench/CMakeLists.txt @@ -0,0 +1,5 @@ +add_llvm_utility(yaml-bench + YAMLBench.cpp + ) + +target_link_libraries(yaml-bench LLVMSupport) diff --git a/utils/yaml-bench/Makefile b/utils/yaml-bench/Makefile new file mode 100644 index 00000000000..07e91226c7a --- /dev/null +++ b/utils/yaml-bench/Makefile @@ -0,0 +1,20 @@ +##===- utils/yaml-bench/Makefile ---------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../.. +TOOLNAME = yaml-bench +USEDLIBS = LLVMSupport.a + +# This tool has no plugins, optimize startup time. +TOOL_NO_EXPORTS = 1 + +# Don't install this utility +NO_INSTALL = 1 + +include $(LEVEL)/Makefile.common diff --git a/utils/yaml-bench/YAMLBench.cpp b/utils/yaml-bench/YAMLBench.cpp new file mode 100644 index 00000000000..e5ee52a16d9 --- /dev/null +++ b/utils/yaml-bench/YAMLBench.cpp @@ -0,0 +1,203 @@ +//===- YAMLBench - Benchmark the YAMLParser implementation ----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This program executes the YAMLParser on differntly sized YAML texts and +// outputs the run time. +// +//===----------------------------------------------------------------------===// + + +#include "llvm/ADT/SmallString.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/Support/system_error.h" +#include "llvm/Support/Timer.h" +#include "llvm/Support/YAMLParser.h" + +using namespace llvm; + +static cl::opt + DumpTokens( "tokens" + , cl::desc("Print the tokenization of the file.") + , cl::init(false) + ); + +static cl::opt + DumpCanonical( "canonical" + , cl::desc("Print the canonical YAML for this file.") + , cl::init(false) + ); + +static cl::opt + Input(cl::Positional, cl::desc("")); + +static cl::opt + Verify( "verify" + , cl::desc( + "Run a quick verification useful for regression testing") + , cl::init(false) + ); + +static cl::opt + MemoryLimitMB("memory-limit", cl::desc( + "Do not use more megabytes of memory"), + cl::init(1000)); + +struct indent { + unsigned distance; + indent(unsigned d) : distance(d) {} +}; + +static raw_ostream &operator <<(raw_ostream &os, const indent &in) { + for (unsigned i = 0; i < in.distance; ++i) + os << " "; + return os; +} + +static void dumpNode( yaml::Node *n + , unsigned Indent = 0 + , bool SuppressFirstIndent = false) { + if (!n) + return; + if (!SuppressFirstIndent) + outs() << indent(Indent); + StringRef Anchor = n->getAnchor(); + if (!Anchor.empty()) + outs() << "&" << Anchor << " "; + if (yaml::ScalarNode *sn = dyn_cast(n)) { + SmallString<32> Storage; + StringRef Val = sn->getValue(Storage); + outs() << "!!str \"" << yaml::escape(Val) << "\""; + } else if (yaml::SequenceNode *sn = dyn_cast(n)) { + outs() << "!!seq [\n"; + ++Indent; + for (yaml::SequenceNode::iterator i = sn->begin(), e = sn->end(); + i != e; ++i) { + dumpNode(i, Indent); + outs() << ",\n"; + } + --Indent; + outs() << indent(Indent) << "]"; + } else if (yaml::MappingNode *mn = dyn_cast(n)) { + outs() << "!!map {\n"; + ++Indent; + for (yaml::MappingNode::iterator i = mn->begin(), e = mn->end(); + i != e; ++i) { + outs() << indent(Indent) << "? "; + dumpNode(i->getKey(), Indent, true); + outs() << "\n"; + outs() << indent(Indent) << ": "; + dumpNode(i->getValue(), Indent, true); + outs() << ",\n"; + } + --Indent; + outs() << indent(Indent) << "}"; + } else if (yaml::AliasNode *an = dyn_cast(n)){ + outs() << "*" << an->getName(); + } else if (dyn_cast(n)) { + outs() << "!!null null"; + } +} + +static void dumpStream(yaml::Stream &stream) { + for (yaml::document_iterator di = stream.begin(), de = stream.end(); di != de; + ++di) { + outs() << "%YAML 1.2\n" + << "---\n"; + yaml::Node *n = di->getRoot(); + if (n) + dumpNode(n); + else + break; + outs() << "\n...\n"; + } +} + +static void benchmark( llvm::TimerGroup &Group + , llvm::StringRef Name + , llvm::StringRef JSONText) { + llvm::Timer BaseLine((Name + ": Loop").str(), Group); + BaseLine.startTimer(); + char C = 0; + for (llvm::StringRef::iterator I = JSONText.begin(), + E = JSONText.end(); + I != E; ++I) { C += *I; } + BaseLine.stopTimer(); + volatile char DontOptimizeOut = C; (void)DontOptimizeOut; + + llvm::Timer Tokenizing((Name + ": Tokenizing").str(), Group); + Tokenizing.startTimer(); + { + yaml::scanTokens(JSONText); + } + Tokenizing.stopTimer(); + + llvm::Timer Parsing((Name + ": Parsing").str(), Group); + Parsing.startTimer(); + { + llvm::SourceMgr SM; + llvm::yaml::Stream stream(JSONText, SM); + stream.skip(); + } + Parsing.stopTimer(); +} + +static std::string createJSONText(size_t MemoryMB, unsigned ValueSize) { + std::string JSONText; + llvm::raw_string_ostream Stream(JSONText); + Stream << "[\n"; + size_t MemoryBytes = MemoryMB * 1024 * 1024; + while (JSONText.size() < MemoryBytes) { + Stream << " {\n" + << " \"key1\": \"" << std::string(ValueSize, '*') << "\",\n" + << " \"key2\": \"" << std::string(ValueSize, '*') << "\",\n" + << " \"key3\": \"" << std::string(ValueSize, '*') << "\"\n" + << " }"; + Stream.flush(); + if (JSONText.size() < MemoryBytes) Stream << ","; + Stream << "\n"; + } + Stream << "]\n"; + Stream.flush(); + return JSONText; +} + +int main(int argc, char **argv) { + llvm::cl::ParseCommandLineOptions(argc, argv); + if (Input.getNumOccurrences()) { + OwningPtr Buf; + if (MemoryBuffer::getFileOrSTDIN(Input, Buf)) + return 1; + + llvm::SourceMgr sm; + if (DumpTokens) { + yaml::dumpTokens(Buf->getBuffer(), outs()); + } + + if (DumpCanonical) { + yaml::Stream stream(Buf->getBuffer(), sm); + dumpStream(stream); + } + } + + if (Verify) { + llvm::TimerGroup Group("YAML parser benchmark"); + benchmark(Group, "Fast", createJSONText(10, 500)); + } else if (!DumpCanonical && !DumpTokens) { + llvm::TimerGroup Group("YAML parser benchmark"); + benchmark(Group, "Small Values", createJSONText(MemoryLimitMB, 5)); + benchmark(Group, "Medium Values", createJSONText(MemoryLimitMB, 500)); + benchmark(Group, "Large Values", createJSONText(MemoryLimitMB, 50000)); + } + + return 0; +} -- cgit v1.2.3