1 /* 2 * Copyright (C) 2011 Google Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.google.gson.metrics; 17 18 import com.google.caliper.BeforeExperiment; 19 import com.google.gson.Gson; 20 import com.google.gson.reflect.TypeToken; 21 import com.google.gson.stream.JsonReader; 22 import java.io.IOException; 23 import java.io.StringReader; 24 import java.lang.reflect.Field; 25 import java.lang.reflect.Type; 26 import java.util.ArrayList; 27 import java.util.List; 28 29 /** 30 * Caliper based micro benchmarks for Gson 31 * 32 * @author Inderjeet Singh 33 */ 34 public class CollectionsDeserializationBenchmark { 35 36 private static final TypeToken<List<BagOfPrimitives>> LIST_TYPE_TOKEN = new TypeToken<List<BagOfPrimitives>>(){}; 37 private static final Type LIST_TYPE = LIST_TYPE_TOKEN.getType(); 38 private Gson gson; 39 private String json; 40 main(String[] args)41 public static void main(String[] args) { 42 NonUploadingCaliperRunner.run(CollectionsDeserializationBenchmark.class, args); 43 } 44 45 @BeforeExperiment setUp()46 void setUp() throws Exception { 47 this.gson = new Gson(); 48 List<BagOfPrimitives> bags = new ArrayList<>(); 49 for (int i = 0; i < 100; ++i) { 50 bags.add(new BagOfPrimitives(10L, 1, false, "foo")); 51 } 52 this.json = gson.toJson(bags, LIST_TYPE); 53 } 54 55 /** 56 * Benchmark to measure Gson performance for deserializing an object 57 */ timeCollectionsDefault(int reps)58 public void timeCollectionsDefault(int reps) { 59 for (int i=0; i<reps; ++i) { 60 gson.fromJson(json, LIST_TYPE_TOKEN); 61 } 62 } 63 64 /** 65 * Benchmark to measure deserializing objects by hand 66 */ timeCollectionsStreaming(int reps)67 public void timeCollectionsStreaming(int reps) throws IOException { 68 for (int i=0; i<reps; ++i) { 69 StringReader reader = new StringReader(json); 70 JsonReader jr = new JsonReader(reader); 71 jr.beginArray(); 72 List<BagOfPrimitives> bags = new ArrayList<>(); 73 while(jr.hasNext()) { 74 jr.beginObject(); 75 long longValue = 0; 76 int intValue = 0; 77 boolean booleanValue = false; 78 String stringValue = null; 79 while(jr.hasNext()) { 80 String name = jr.nextName(); 81 if (name.equals("longValue")) { 82 longValue = jr.nextLong(); 83 } else if (name.equals("intValue")) { 84 intValue = jr.nextInt(); 85 } else if (name.equals("booleanValue")) { 86 booleanValue = jr.nextBoolean(); 87 } else if (name.equals("stringValue")) { 88 stringValue = jr.nextString(); 89 } else { 90 throw new IOException("Unexpected name: " + name); 91 } 92 } 93 jr.endObject(); 94 bags.add(new BagOfPrimitives(longValue, intValue, booleanValue, stringValue)); 95 } 96 jr.endArray(); 97 } 98 } 99 100 /** 101 * This benchmark measures the ideal Gson performance: the cost of parsing a JSON stream and 102 * setting object values by reflection. We should strive to reduce the discrepancy between this 103 * and {@link #timeCollectionsDefault(int)} . 104 */ timeCollectionsReflectionStreaming(int reps)105 public void timeCollectionsReflectionStreaming(int reps) throws Exception { 106 for (int i=0; i<reps; ++i) { 107 StringReader reader = new StringReader(json); 108 JsonReader jr = new JsonReader(reader); 109 jr.beginArray(); 110 List<BagOfPrimitives> bags = new ArrayList<>(); 111 while(jr.hasNext()) { 112 jr.beginObject(); 113 BagOfPrimitives bag = new BagOfPrimitives(); 114 while(jr.hasNext()) { 115 String name = jr.nextName(); 116 for (Field field : BagOfPrimitives.class.getDeclaredFields()) { 117 if (field.getName().equals(name)) { 118 Class<?> fieldType = field.getType(); 119 if (fieldType.equals(long.class)) { 120 field.setLong(bag, jr.nextLong()); 121 } else if (fieldType.equals(int.class)) { 122 field.setInt(bag, jr.nextInt()); 123 } else if (fieldType.equals(boolean.class)) { 124 field.setBoolean(bag, jr.nextBoolean()); 125 } else if (fieldType.equals(String.class)) { 126 field.set(bag, jr.nextString()); 127 } else { 128 throw new RuntimeException("Unexpected: type: " + fieldType + ", name: " + name); 129 } 130 } 131 } 132 } 133 jr.endObject(); 134 bags.add(bag); 135 } 136 jr.endArray(); 137 } 138 } 139 } 140