aboutsummaryrefslogtreecommitdiffstats
path: root/metrics/src/main/java/com/google/gson/metrics/ParseBenchmark.java
diff options
context:
space:
mode:
Diffstat (limited to 'metrics/src/main/java/com/google/gson/metrics/ParseBenchmark.java')
-rw-r--r--metrics/src/main/java/com/google/gson/metrics/ParseBenchmark.java389
1 files changed, 389 insertions, 0 deletions
diff --git a/metrics/src/main/java/com/google/gson/metrics/ParseBenchmark.java b/metrics/src/main/java/com/google/gson/metrics/ParseBenchmark.java
new file mode 100644
index 00000000..68134372
--- /dev/null
+++ b/metrics/src/main/java/com/google/gson/metrics/ParseBenchmark.java
@@ -0,0 +1,389 @@
+/*
+ * 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 com.google.gson.metrics;
+
+import com.google.caliper.Param;
+import com.google.caliper.Runner;
+import com.google.caliper.SimpleBenchmark;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonParser;
+import com.google.gson.annotations.SerializedName;
+import com.google.gson.reflect.TypeToken;
+import java.io.CharArrayReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.io.StringWriter;
+import java.lang.reflect.Type;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.List;
+import org.codehaus.jackson.JsonFactory;
+import org.codehaus.jackson.annotate.JsonProperty;
+import org.codehaus.jackson.map.DeserializationConfig;
+import org.codehaus.jackson.map.ObjectMapper;
+import org.codehaus.jackson.type.TypeReference;
+
+/**
+ * Measure Gson and Jackson parsing and binding performance.
+ *
+ * <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(new TypeToken<List<Tweet>>() {}, new TypeReference<List<Tweet>>() {}),
+ READER_SHORT(new TypeToken<Feed>() {}, new TypeReference<Feed>() {}),
+ READER_LONG(new TypeToken<Feed>() {}, new TypeReference<Feed>() {});
+
+ private final Type gsonType;
+ private final TypeReference<?> jacksonType;
+
+ private Document(TypeToken<?> typeToken, TypeReference<?> typeReference) {
+ this.gsonType = typeToken.getType();
+ this.jacksonType = typeReference;
+ }
+ }
+
+ private enum Api {
+ JACKSON_STREAM {
+ @Override Parser newParser() {
+ return new JacksonStreamParser();
+ }
+ },
+ JACKSON_BIND {
+ @Override Parser newParser() {
+ return new JacksonBindParser();
+ }
+ },
+ GSON_STREAM {
+ @Override Parser newParser() {
+ return new GsonStreamParser();
+ }
+ },
+ GSON_SKIP {
+ @Override Parser newParser() {
+ return new GsonSkipParser();
+ }
+ },
+ GSON_DOM {
+ @Override Parser newParser() {
+ return new GsonDomParser();
+ }
+ },
+ GSON_BIND {
+ @Override Parser newParser() {
+ return new GsonBindParser();
+ }
+ };
+ abstract Parser newParser();
+ }
+
+ private char[] text;
+ private Parser parser;
+
+ @Override protected void setUp() throws Exception {
+ text = resourceToString("/" + document.name() + ".json").toCharArray();
+ parser = api.newParser();
+ }
+
+ public void timeParse(int reps) throws Exception {
+ for (int i = 0; i < reps; i++) {
+ parser.parse(text, document);
+ }
+ }
+
+ 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();
+ }
+
+ public static void main(String[] args) throws Exception {
+ Runner.main(ParseBenchmark.class, args);
+ }
+
+ interface Parser {
+ void parse(char[] data, Document document) throws Exception;
+ }
+
+ private static class GsonStreamParser implements Parser {
+ public void parse(char[] data, Document document) throws Exception {
+ com.google.gson.stream.JsonReader jsonReader
+ = new com.google.gson.stream.JsonReader(new CharArrayReader(data));
+ readToken(jsonReader);
+ jsonReader.close();
+ }
+
+ private void readToken(com.google.gson.stream.JsonReader reader) throws IOException {
+ while (true) {
+ switch (reader.peek()) {
+ case BEGIN_ARRAY:
+ reader.beginArray();
+ break;
+ case END_ARRAY:
+ reader.endArray();
+ break;
+ case BEGIN_OBJECT:
+ reader.beginObject();
+ break;
+ case END_OBJECT:
+ reader.endObject();
+ break;
+ case NAME:
+ reader.nextName();
+ break;
+ case BOOLEAN:
+ reader.nextBoolean();
+ break;
+ case NULL:
+ reader.nextNull();
+ break;
+ case NUMBER:
+ reader.nextLong();
+ break;
+ case STRING:
+ reader.nextString();
+ break;
+ case END_DOCUMENT:
+ return;
+ default:
+ throw new IllegalArgumentException("Unexpected token" + reader.peek());
+ }
+ }
+ }
+ }
+
+ private static class GsonSkipParser implements Parser {
+ public void parse(char[] data, Document document) throws Exception {
+ com.google.gson.stream.JsonReader jsonReader
+ = new com.google.gson.stream.JsonReader(new CharArrayReader(data));
+ jsonReader.skipValue();
+ jsonReader.close();
+ }
+ }
+
+ private static class JacksonStreamParser implements Parser {
+ public void parse(char[] data, Document document) throws Exception {
+ JsonFactory jsonFactory = new JsonFactory();
+ org.codehaus.jackson.JsonParser jp = jsonFactory.createJsonParser(new CharArrayReader(data));
+ jp.configure(org.codehaus.jackson.JsonParser.Feature.CANONICALIZE_FIELD_NAMES, false);
+ int depth = 0;
+ do {
+ switch (jp.nextToken()) {
+ case START_OBJECT:
+ case START_ARRAY:
+ depth++;
+ break;
+ case END_OBJECT:
+ case END_ARRAY:
+ depth--;
+ break;
+ case FIELD_NAME:
+ jp.getCurrentName();
+ break;
+ case VALUE_STRING:
+ jp.getText();
+ break;
+ case VALUE_NUMBER_INT:
+ case VALUE_NUMBER_FLOAT:
+ jp.getLongValue();
+ break;
+ }
+ } while (depth > 0);
+ jp.close();
+ }
+ }
+
+ private static class GsonDomParser implements Parser {
+ public void parse(char[] data, Document document) throws Exception {
+ new JsonParser().parse(new CharArrayReader(data));
+ }
+ }
+
+ private static class GsonBindParser implements Parser {
+ private static Gson gson = new GsonBuilder()
+ .setDateFormat("EEE MMM dd HH:mm:ss Z yyyy")
+ .create();
+
+ public void parse(char[] data, Document document) throws Exception {
+ gson.fromJson(new CharArrayReader(data), document.gsonType);
+ }
+ }
+
+ private static class JacksonBindParser implements Parser {
+ private static ObjectMapper mapper = new ObjectMapper();
+
+ static {
+ mapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+ mapper.configure(DeserializationConfig.Feature.AUTO_DETECT_FIELDS, true);
+ mapper.setDateFormat(new SimpleDateFormat("EEE MMM dd HH:mm:ss Z yyyy"));
+ }
+
+ public void parse(char[] data, Document document) throws Exception {
+ mapper.readValue(new CharArrayReader(data), document.jacksonType);
+ }
+ }
+
+ static class Tweet {
+ @JsonProperty String coordinates;
+ @JsonProperty boolean favorited;
+ @JsonProperty Date created_at;
+ @JsonProperty boolean truncated;
+ @JsonProperty Tweet retweeted_status;
+ @JsonProperty String id_str;
+ @JsonProperty String in_reply_to_id_str;
+ @JsonProperty String contributors;
+ @JsonProperty String text;
+ @JsonProperty long id;
+ @JsonProperty String retweet_count;
+ @JsonProperty String in_reply_to_status_id_str;
+ @JsonProperty Object geo;
+ @JsonProperty boolean retweeted;
+ @JsonProperty String in_reply_to_user_id;
+ @JsonProperty String in_reply_to_screen_name;
+ @JsonProperty Object place;
+ @JsonProperty User user;
+ @JsonProperty String source;
+ @JsonProperty String in_reply_to_user_id_str;
+ }
+
+ static class User {
+ @JsonProperty String name;
+ @JsonProperty String profile_sidebar_border_color;
+ @JsonProperty boolean profile_background_tile;
+ @JsonProperty String profile_sidebar_fill_color;
+ @JsonProperty Date created_at;
+ @JsonProperty String location;
+ @JsonProperty String profile_image_url;
+ @JsonProperty boolean follow_request_sent;
+ @JsonProperty String profile_link_color;
+ @JsonProperty boolean is_translator;
+ @JsonProperty String id_str;
+ @JsonProperty int favourites_count;
+ @JsonProperty boolean contributors_enabled;
+ @JsonProperty String url;
+ @JsonProperty boolean default_profile;
+ @JsonProperty long utc_offset;
+ @JsonProperty long id;
+ @JsonProperty boolean profile_use_background_image;
+ @JsonProperty int listed_count;
+ @JsonProperty String lang;
+ @JsonProperty("protected") @SerializedName("protected") boolean isProtected;
+ @JsonProperty int followers_count;
+ @JsonProperty String profile_text_color;
+ @JsonProperty String profile_background_color;
+ @JsonProperty String time_zone;
+ @JsonProperty String description;
+ @JsonProperty boolean notifications;
+ @JsonProperty boolean geo_enabled;
+ @JsonProperty boolean verified;
+ @JsonProperty String profile_background_image_url;
+ @JsonProperty boolean defalut_profile_image;
+ @JsonProperty int friends_count;
+ @JsonProperty int statuses_count;
+ @JsonProperty String screen_name;
+ @JsonProperty boolean following;
+ @JsonProperty boolean show_all_inline_media;
+ }
+
+ static class Feed {
+ @JsonProperty String id;
+ @JsonProperty String title;
+ @JsonProperty String description;
+ @JsonProperty("alternate") @SerializedName("alternate") List<Link> alternates;
+ @JsonProperty long updated;
+ @JsonProperty List<Item> items;
+
+ @Override public String toString() {
+ StringBuilder result = new StringBuilder()
+ .append(id)
+ .append("\n").append(title)
+ .append("\n").append(description)
+ .append("\n").append(alternates)
+ .append("\n").append(updated);
+ int i = 1;
+ for (Item item : items) {
+ result.append(i++).append(": ").append(item).append("\n\n");
+ }
+ return result.toString();
+ }
+ }
+
+ static class Link {
+ @JsonProperty String href;
+
+ @Override public String toString() {
+ return href;
+ }
+ }
+
+ static class Item {
+ @JsonProperty List<String> categories;
+ @JsonProperty String title;
+ @JsonProperty long published;
+ @JsonProperty long updated;
+ @JsonProperty("alternate") @SerializedName("alternate") List<Link> alternates;
+ @JsonProperty Content content;
+ @JsonProperty String author;
+ @JsonProperty List<ReaderUser> likingUsers;
+
+ @Override public String toString() {
+ return title
+ + "\nauthor: " + author
+ + "\npublished: " + published
+ + "\nupdated: " + updated
+ + "\n" + content
+ + "\nliking users: " + likingUsers
+ + "\nalternates: " + alternates
+ + "\ncategories: " + categories;
+ }
+ }
+
+ static class Content {
+ @JsonProperty String content;
+
+ @Override public String toString() {
+ return content;
+ }
+ }
+
+ static class ReaderUser {
+ @JsonProperty String userId;
+
+ @Override public String toString() {
+ return userId;
+ }
+ }
+}