346 lines
10 KiB
Java
346 lines
10 KiB
Java
/*
|
|
* Copyright (C) 2008 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.gson.Gson;
|
|
import com.google.gson.JsonParseException;
|
|
import com.google.gson.annotations.Expose;
|
|
import com.google.gson.reflect.TypeToken;
|
|
|
|
import junit.framework.TestCase;
|
|
|
|
import java.io.StringWriter;
|
|
import java.lang.reflect.Type;
|
|
import java.util.ArrayList;
|
|
import java.util.HashMap;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
|
|
/**
|
|
* Tests to measure performance for Gson. All tests in this file will be disabled in code. To run
|
|
* them remove disabled_ prefix from the tests and run them.
|
|
*
|
|
* @author Inderjeet Singh
|
|
* @author Joel Leitch
|
|
*/
|
|
public class PerformanceTest extends TestCase {
|
|
private static final int COLLECTION_SIZE = 5000;
|
|
|
|
private static final int NUM_ITERATIONS = 100;
|
|
|
|
private Gson gson;
|
|
|
|
@Override
|
|
protected void setUp() throws Exception {
|
|
super.setUp();
|
|
gson = new Gson();
|
|
}
|
|
|
|
public void testDummy() {
|
|
// This is here to prevent Junit for complaining when we disable all tests.
|
|
}
|
|
|
|
public void disabled_testStringDeserialization() {
|
|
StringBuilder sb = new StringBuilder(8096);
|
|
sb.append("Error Yippie");
|
|
|
|
while (true) {
|
|
try {
|
|
String stackTrace = sb.toString();
|
|
sb.append(stackTrace);
|
|
String json = "{\"message\":\"Error message.\"," + "\"stackTrace\":\"" + stackTrace + "\"}";
|
|
parseLongJson(json);
|
|
System.out.println("Gson could handle a string of size: " + stackTrace.length());
|
|
} catch (JsonParseException expected) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void parseLongJson(String json) throws JsonParseException {
|
|
ExceptionHolder target = gson.fromJson(json, ExceptionHolder.class);
|
|
assertTrue(target.message.contains("Error"));
|
|
assertTrue(target.stackTrace.contains("Yippie"));
|
|
}
|
|
|
|
private static class ExceptionHolder {
|
|
public final String message;
|
|
public final String stackTrace;
|
|
|
|
// For use by Gson
|
|
@SuppressWarnings("unused")
|
|
private ExceptionHolder() {
|
|
this("", "");
|
|
}
|
|
public ExceptionHolder(String message, String stackTrace) {
|
|
this.message = message;
|
|
this.stackTrace = stackTrace;
|
|
}
|
|
}
|
|
|
|
@SuppressWarnings("unused")
|
|
private static class CollectionEntry {
|
|
final String name;
|
|
final String value;
|
|
|
|
// For use by Gson
|
|
private CollectionEntry() {
|
|
this(null, null);
|
|
}
|
|
|
|
CollectionEntry(String name, String value) {
|
|
this.name = name;
|
|
this.value = value;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Created in response to http://code.google.com/p/google-gson/issues/detail?id=96
|
|
*/
|
|
public void disabled_testLargeCollectionSerialization() {
|
|
int count = 1400000;
|
|
List<CollectionEntry> list = new ArrayList<>(count);
|
|
for (int i = 0; i < count; ++i) {
|
|
list.add(new CollectionEntry("name"+i,"value"+i));
|
|
}
|
|
gson.toJson(list);
|
|
}
|
|
|
|
/**
|
|
* Created in response to http://code.google.com/p/google-gson/issues/detail?id=96
|
|
*/
|
|
public void disabled_testLargeCollectionDeserialization() {
|
|
StringBuilder sb = new StringBuilder();
|
|
int count = 87000;
|
|
boolean first = true;
|
|
sb.append('[');
|
|
for (int i = 0; i < count; ++i) {
|
|
if (first) {
|
|
first = false;
|
|
} else {
|
|
sb.append(',');
|
|
}
|
|
sb.append("{name:'name").append(i).append("',value:'value").append(i).append("'}");
|
|
}
|
|
sb.append(']');
|
|
String json = sb.toString();
|
|
Type collectionType = new TypeToken<ArrayList<CollectionEntry>>(){}.getType();
|
|
List<CollectionEntry> list = gson.fromJson(json, collectionType);
|
|
assertEquals(count, list.size());
|
|
}
|
|
|
|
/**
|
|
* Created in response to http://code.google.com/p/google-gson/issues/detail?id=96
|
|
*/
|
|
// Last I tested, Gson was able to serialize upto 14MB byte array
|
|
public void disabled_testByteArraySerialization() {
|
|
for (int size = 4145152; true; size += 1036288) {
|
|
byte[] ba = new byte[size];
|
|
for (int i = 0; i < size; ++i) {
|
|
ba[i] = 0x05;
|
|
}
|
|
gson.toJson(ba);
|
|
System.out.printf("Gson could serialize a byte array of size: %d\n", size);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Created in response to http://code.google.com/p/google-gson/issues/detail?id=96
|
|
*/
|
|
// Last I tested, Gson was able to deserialize a byte array of 11MB
|
|
public void disable_testByteArrayDeserialization() {
|
|
for (int numElements = 10639296; true; numElements += 16384) {
|
|
StringBuilder sb = new StringBuilder(numElements*2);
|
|
sb.append("[");
|
|
boolean first = true;
|
|
for (int i = 0; i < numElements; ++i) {
|
|
if (first) {
|
|
first = false;
|
|
} else {
|
|
sb.append(",");
|
|
}
|
|
sb.append("5");
|
|
}
|
|
sb.append("]");
|
|
String json = sb.toString();
|
|
byte[] ba = gson.fromJson(json, byte[].class);
|
|
System.out.printf("Gson could deserialize a byte array of size: %d\n", ba.length);
|
|
}
|
|
}
|
|
|
|
// The tests to measure serialization and deserialization performance of Gson
|
|
// Based on the discussion at
|
|
// http://groups.google.com/group/google-gson/browse_thread/thread/7a50b17a390dfaeb
|
|
// Test results: 10/19/2009
|
|
// Serialize classes avg time: 60 ms
|
|
// Deserialized classes avg time: 70 ms
|
|
// Serialize exposed classes avg time: 159 ms
|
|
// Deserialized exposed classes avg time: 173 ms
|
|
|
|
public void disabled_testSerializeClasses() {
|
|
ClassWithList c = new ClassWithList("str");
|
|
for (int i = 0; i < COLLECTION_SIZE; ++i) {
|
|
c.list.add(new ClassWithField("element-" + i));
|
|
}
|
|
StringWriter w = new StringWriter();
|
|
long t1 = System.currentTimeMillis();
|
|
for (int i = 0; i < NUM_ITERATIONS; ++i) {
|
|
gson.toJson(c, w);
|
|
}
|
|
long t2 = System.currentTimeMillis();
|
|
long avg = (t2 - t1) / NUM_ITERATIONS;
|
|
System.out.printf("Serialize classes avg time: %d ms\n", avg);
|
|
}
|
|
|
|
public void disabled_testDeserializeClasses() {
|
|
String json = buildJsonForClassWithList();
|
|
ClassWithList[] target = new ClassWithList[NUM_ITERATIONS];
|
|
long t1 = System.currentTimeMillis();
|
|
for (int i = 0; i < NUM_ITERATIONS; ++i) {
|
|
target[i] = gson.fromJson(json, ClassWithList.class);
|
|
}
|
|
long t2 = System.currentTimeMillis();
|
|
long avg = (t2 - t1) / NUM_ITERATIONS;
|
|
System.out.printf("Deserialize classes avg time: %d ms\n", avg);
|
|
}
|
|
|
|
public void disable_testLargeObjectSerializationAndDeserialization() {
|
|
Map<String, Long> largeObject = new HashMap<>();
|
|
for (long l = 0; l < 100000; l++) {
|
|
largeObject.put("field" + l, l);
|
|
}
|
|
|
|
long t1 = System.currentTimeMillis();
|
|
String json = gson.toJson(largeObject);
|
|
long t2 = System.currentTimeMillis();
|
|
System.out.printf("Large object serialized in: %d ms\n", (t2 - t1));
|
|
|
|
t1 = System.currentTimeMillis();
|
|
gson.fromJson(json, new TypeToken<Map<String, Long>>() {}.getType());
|
|
t2 = System.currentTimeMillis();
|
|
System.out.printf("Large object deserialized in: %d ms\n", (t2 - t1));
|
|
|
|
}
|
|
|
|
public void disabled_testSerializeExposedClasses() {
|
|
ClassWithListOfObjects c1 = new ClassWithListOfObjects("str");
|
|
for (int i1 = 0; i1 < COLLECTION_SIZE; ++i1) {
|
|
c1.list.add(new ClassWithExposedField("element-" + i1));
|
|
}
|
|
ClassWithListOfObjects c = c1;
|
|
StringWriter w = new StringWriter();
|
|
long t1 = System.currentTimeMillis();
|
|
for (int i = 0; i < NUM_ITERATIONS; ++i) {
|
|
gson.toJson(c, w);
|
|
}
|
|
long t2 = System.currentTimeMillis();
|
|
long avg = (t2 - t1) / NUM_ITERATIONS;
|
|
System.out.printf("Serialize exposed classes avg time: %d ms\n", avg);
|
|
}
|
|
|
|
public void disabled_testDeserializeExposedClasses() {
|
|
String json = buildJsonForClassWithList();
|
|
ClassWithListOfObjects[] target = new ClassWithListOfObjects[NUM_ITERATIONS];
|
|
long t1 = System.currentTimeMillis();
|
|
for (int i = 0; i < NUM_ITERATIONS; ++i) {
|
|
target[i] = gson.fromJson(json, ClassWithListOfObjects.class);
|
|
}
|
|
long t2 = System.currentTimeMillis();
|
|
long avg = (t2 - t1) / NUM_ITERATIONS;
|
|
System.out.printf("Deserialize exposed classes avg time: %d ms\n", avg);
|
|
}
|
|
|
|
public void disabled_testLargeGsonMapRoundTrip() throws Exception {
|
|
Map<Long, Long> original = new HashMap<>();
|
|
for (long i = 0; i < 1000000; i++) {
|
|
original.put(i, i + 1);
|
|
}
|
|
|
|
Gson gson = new Gson();
|
|
String json = gson.toJson(original);
|
|
Type longToLong = new TypeToken<Map<Long, Long>>(){}.getType();
|
|
gson.fromJson(json, longToLong);
|
|
}
|
|
|
|
private String buildJsonForClassWithList() {
|
|
StringBuilder sb = new StringBuilder("{");
|
|
sb.append("field:").append("'str',");
|
|
sb.append("list:[");
|
|
boolean first = true;
|
|
for (int i = 0; i < COLLECTION_SIZE; ++i) {
|
|
if (first) {
|
|
first = false;
|
|
} else {
|
|
sb.append(",");
|
|
}
|
|
sb.append("{field:'element-" + i + "'}");
|
|
}
|
|
sb.append("]");
|
|
sb.append("}");
|
|
String json = sb.toString();
|
|
return json;
|
|
}
|
|
|
|
@SuppressWarnings("unused")
|
|
private static final class ClassWithList {
|
|
final String field;
|
|
final List<ClassWithField> list = new ArrayList<>(COLLECTION_SIZE);
|
|
ClassWithList() {
|
|
this(null);
|
|
}
|
|
ClassWithList(String field) {
|
|
this.field = field;
|
|
}
|
|
}
|
|
|
|
@SuppressWarnings("unused")
|
|
private static final class ClassWithField {
|
|
final String field;
|
|
ClassWithField() {
|
|
this("");
|
|
}
|
|
public ClassWithField(String field) {
|
|
this.field = field;
|
|
}
|
|
}
|
|
|
|
@SuppressWarnings("unused")
|
|
private static final class ClassWithListOfObjects {
|
|
@Expose
|
|
final String field;
|
|
@Expose
|
|
final List<ClassWithExposedField> list = new ArrayList<>(COLLECTION_SIZE);
|
|
ClassWithListOfObjects() {
|
|
this(null);
|
|
}
|
|
ClassWithListOfObjects(String field) {
|
|
this.field = field;
|
|
}
|
|
}
|
|
|
|
@SuppressWarnings("unused")
|
|
private static final class ClassWithExposedField {
|
|
@Expose
|
|
final String field;
|
|
ClassWithExposedField() {
|
|
this("");
|
|
}
|
|
ClassWithExposedField(String field) {
|
|
this.field = field;
|
|
}
|
|
}
|
|
} |