Check in our best Jackson vs. Gson comparison benchmarks.
http://microbenchmarks.appspot.com/run/limpbizkit@gmail.com/com.google.gson.metrics.ParseBenchmark
This commit is contained in:
parent
b7c3e0067c
commit
5acaee4ebc
|
@ -0,0 +1,379 @@
|
|||
/*
|
||||
* 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_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();
|
||||
}
|
||||
|
||||
public void readObject(com.google.gson.stream.JsonReader reader) throws IOException {
|
||||
reader.beginObject();
|
||||
while (reader.hasNext()) {
|
||||
reader.nextName();
|
||||
readToken(reader);
|
||||
}
|
||||
reader.endObject();
|
||||
}
|
||||
|
||||
public void readArray(com.google.gson.stream.JsonReader reader) throws IOException {
|
||||
reader.beginArray();
|
||||
while (reader.hasNext()) {
|
||||
readToken(reader);
|
||||
}
|
||||
reader.endArray();
|
||||
}
|
||||
|
||||
private void readToken(com.google.gson.stream.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 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;
|
||||
}
|
||||
}
|
||||
}
|
Binary file not shown.
Loading…
Reference in New Issue
Block a user