diff options
Diffstat (limited to 'benchmarks/regression/ParseBenchmark.java')
-rw-r--r-- | benchmarks/regression/ParseBenchmark.java | 217 |
1 files changed, 217 insertions, 0 deletions
diff --git a/benchmarks/regression/ParseBenchmark.java b/benchmarks/regression/ParseBenchmark.java new file mode 100644 index 0000000..b44b429 --- /dev/null +++ b/benchmarks/regression/ParseBenchmark.java @@ -0,0 +1,217 @@ +/* + * Copyright (C) 2011 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package benchmarks.regression; + +import com.google.caliper.Param; +import com.google.caliper.Runner; +import com.google.caliper.SimpleBenchmark; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.io.StringReader; +import java.io.StringWriter; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.SAXParserFactory; +import org.json.JSONArray; +import org.json.JSONObject; +import org.xml.sax.InputSource; +import org.xml.sax.helpers.DefaultHandler; +import org.xmlpull.v1.XmlPullParser; + +/** + * Measure throughput of various parsers. + * + * <p>This benchmark requires that ParseBenchmarkData.zip is on the classpath. + * That file contains Twitter feed data, which is representative of what + * applications will be parsing. + */ +public final class ParseBenchmark extends SimpleBenchmark { + + @Param Document document; + @Param Api api; + + private enum Document { + TWEETS, + READER_SHORT, + READER_LONG + } + + private enum Api { + ANDROID_STREAM("json") { + @Override Parser newParser() { + return new AndroidStreamParser(); + } + }, + ORG_JSON("json") { + @Override Parser newParser() { + return new OrgJsonParser(); + } + }, + XML_PULL("xml") { + @Override Parser newParser() { + return new GeneralXmlPullParser(); + } + }, + XML_DOM("xml") { + @Override Parser newParser() { + return new XmlDomParser(); + } + }, + XML_SAX("xml") { + @Override Parser newParser() { + return new XmlSaxParser(); + } + }; + + final String extension; + + private Api(String extension) { + this.extension = extension; + } + + abstract Parser newParser(); + } + + private String text; + private Parser parser; + + @Override protected void setUp() throws Exception { + text = resourceToString("/" + document.name() + "." + api.extension); + parser = api.newParser(); + } + + public void timeParse(int reps) throws Exception { + for (int i = 0; i < reps; i++) { + parser.parse(text); + } + } + + public static void main(String... args) throws Exception { + Runner.main(ParseBenchmark.class, args); + } + + private static String resourceToString(String path) throws Exception { + InputStream in = ParseBenchmark.class.getResourceAsStream(path); + if (in == null) { + throw new IllegalArgumentException("No such file: " + path); + } + + Reader reader = new InputStreamReader(in, "UTF-8"); + char[] buffer = new char[8192]; + StringWriter writer = new StringWriter(); + int count; + while ((count = reader.read(buffer)) != -1) { + writer.write(buffer, 0, count); + } + reader.close(); + return writer.toString(); + } + + interface Parser { + void parse(String data) throws Exception; + } + + private static class AndroidStreamParser implements Parser { + @Override public void parse(String data) throws Exception { + android.util.JsonReader jsonReader + = new android.util.JsonReader(new StringReader(data)); + readToken(jsonReader); + jsonReader.close(); + } + + public void readObject(android.util.JsonReader reader) throws IOException { + reader.beginObject(); + while (reader.hasNext()) { + reader.nextName(); + readToken(reader); + } + reader.endObject(); + } + + public void readArray(android.util.JsonReader reader) throws IOException { + reader.beginArray(); + while (reader.hasNext()) { + readToken(reader); + } + reader.endArray(); + } + + private void readToken(android.util.JsonReader reader) throws IOException { + switch (reader.peek()) { + case BEGIN_ARRAY: + readArray(reader); + break; + case BEGIN_OBJECT: + readObject(reader); + break; + case BOOLEAN: + reader.nextBoolean(); + break; + case NULL: + reader.nextNull(); + break; + case NUMBER: + reader.nextLong(); + break; + case STRING: + reader.nextString(); + break; + default: + throw new IllegalArgumentException("Unexpected token" + reader.peek()); + } + } + } + + private static class OrgJsonParser implements Parser { + @Override public void parse(String data) throws Exception { + if (data.startsWith("[")) { + new JSONArray(data); + } else if (data.startsWith("{")) { + new JSONObject(data); + } else { + throw new IllegalArgumentException(); + } + } + } + + private static class GeneralXmlPullParser implements Parser { + @Override public void parse(String data) throws Exception { + XmlPullParser xmlParser = android.util.Xml.newPullParser(); + xmlParser.setInput(new StringReader(data)); + xmlParser.nextTag(); + while (xmlParser.next() != XmlPullParser.END_DOCUMENT) { + xmlParser.getName(); + xmlParser.getText(); + } + } + } + + private static class XmlDomParser implements Parser { + @Override public void parse(String data) throws Exception { + DocumentBuilderFactory.newInstance().newDocumentBuilder() + .parse(new InputSource(new StringReader(data))); + } + } + + private static class XmlSaxParser implements Parser { + @Override public void parse(String data) throws Exception { + SAXParserFactory.newInstance().newSAXParser().parse( + new InputSource(new StringReader(data)), new DefaultHandler()); + } + } +} |