From 764e4d9aca8139540f3b37ec3977c07e3e705127 Mon Sep 17 00:00:00 2001 From: Joel Leitch Date: Tue, 20 Jan 2009 08:38:21 +0000 Subject: [PATCH] Performance fixes after doing some profiling. --- .../com/google/gson/DefaultTypeAdapters.java | 2 +- .../gson/DisjunctionExclusionStrategy.java | 16 +------ gson/src/main/java/com/google/gson/Gson.java | 11 +---- .../java/com/google/gson/GsonBuilder.java | 47 +++++++++++-------- .../com/google/gson/JsonTreeNavigator.java | 2 +- .../google/gson/MappedObjectConstructor.java | 8 +++- .../google/gson/ObjectNavigatorFactory.java | 12 ----- .../DisjunctionExclusionStrategyTest.java | 29 +++--------- 8 files changed, 45 insertions(+), 82 deletions(-) diff --git a/gson/src/main/java/com/google/gson/DefaultTypeAdapters.java b/gson/src/main/java/com/google/gson/DefaultTypeAdapters.java index 20302d53..c16db93f 100644 --- a/gson/src/main/java/com/google/gson/DefaultTypeAdapters.java +++ b/gson/src/main/java/com/google/gson/DefaultTypeAdapters.java @@ -429,7 +429,7 @@ final class DefaultTypeAdapters { return new LinkedList(); } } - + private static class PropertiesCreator implements InstanceCreator { public Properties createInstance(Type type) { return new Properties(); diff --git a/gson/src/main/java/com/google/gson/DisjunctionExclusionStrategy.java b/gson/src/main/java/com/google/gson/DisjunctionExclusionStrategy.java index 76799a63..236c0a43 100644 --- a/gson/src/main/java/com/google/gson/DisjunctionExclusionStrategy.java +++ b/gson/src/main/java/com/google/gson/DisjunctionExclusionStrategy.java @@ -18,7 +18,6 @@ package com.google.gson; import java.lang.reflect.Field; import java.util.Collection; -import java.util.LinkedList; /** * A wrapper class used to collect numerous {@link ExclusionStrategy} objects @@ -29,22 +28,9 @@ import java.util.LinkedList; final class DisjunctionExclusionStrategy implements ExclusionStrategy { private final Collection strategies; - public DisjunctionExclusionStrategy(ExclusionStrategy... strategies) { - Preconditions.checkNotNull(strategies); - Preconditions.checkArgument(strategies.length > 0); - - this.strategies = new LinkedList(); - for (ExclusionStrategy strategy : strategies) { - this.strategies.add(strategy); - } - } - public DisjunctionExclusionStrategy(Collection strategies) { Preconditions.checkNotNull(strategies); - Preconditions.checkArgument(!strategies.isEmpty()); - - this.strategies = new LinkedList(); - this.strategies.addAll(strategies); + this.strategies = strategies; } public boolean shouldSkipField(Field f) { diff --git a/gson/src/main/java/com/google/gson/Gson.java b/gson/src/main/java/com/google/gson/Gson.java index 6520ec09..a9c11271 100644 --- a/gson/src/main/java/com/google/gson/Gson.java +++ b/gson/src/main/java/com/google/gson/Gson.java @@ -140,7 +140,7 @@ public final class Gson { */ Gson(ExclusionStrategy strategy, FieldNamingStrategy fieldNamingPolicy) { this(strategy, fieldNamingPolicy, - createObjectConstructor(DefaultTypeAdapters.getDefaultInstanceCreators()), + new MappedObjectConstructor(DefaultTypeAdapters.getDefaultInstanceCreators()), DEFAULT_JSON_FORMATTER, false, DefaultTypeAdapters.getDefaultSerializers(), DefaultTypeAdapters.getDefaultDeserializers()); } @@ -158,15 +158,6 @@ public final class Gson { this.deserializers = deserializers; } - static MappedObjectConstructor createObjectConstructor( - ParameterizedTypeHandlerMap> instanceCreators) { - MappedObjectConstructor objectConstructor = new MappedObjectConstructor(); - for (Map.Entry> entry : instanceCreators.entrySet()) { - objectConstructor.register(entry.getKey(), entry.getValue()); - } - return objectConstructor; - } - private ObjectNavigatorFactory createDefaultObjectNavigatorFactory() { return new ObjectNavigatorFactory(strategy, fieldNamingPolicy); } diff --git a/gson/src/main/java/com/google/gson/GsonBuilder.java b/gson/src/main/java/com/google/gson/GsonBuilder.java index a3297569..f92e4814 100644 --- a/gson/src/main/java/com/google/gson/GsonBuilder.java +++ b/gson/src/main/java/com/google/gson/GsonBuilder.java @@ -50,12 +50,16 @@ import com.google.gson.DefaultTypeAdapters.DefaultDateTypeAdapter; * @author Joel Leitch */ public final class GsonBuilder { - + private static final AnonymousAndLocalClassExclusionStrategy anonAndLocalClassExclusionStrategy = + new AnonymousAndLocalClassExclusionStrategy(); + private static final InnerClassExclusionStrategy innerClassExclusionStrategy = + new InnerClassExclusionStrategy(); + private static final ExposeAnnotationBasedExclusionStrategy exposeAnnotationExclusionStrategy = + new ExposeAnnotationBasedExclusionStrategy(); + private double ignoreVersionsAfter; private ModifierBasedExclusionStrategy modifierBasedExclusionStrategy; private boolean serializeInnerClasses; - private final AnonymousAndLocalClassExclusionStrategy anonAndLocalClassExclusionStrategy; - private final InnerClassExclusionStrategy innerClassExclusionStrategy; private boolean excludeFieldsWithoutExposeAnnotation; private LongSerializationPolicy longSerializationPolicy; private FieldNamingStrategy fieldNamingPolicy; @@ -82,8 +86,6 @@ public final class GsonBuilder { serializeInnerClasses = true; prettyPrinting = false; escapeHtmlChars = true; - anonAndLocalClassExclusionStrategy = new AnonymousAndLocalClassExclusionStrategy(); - innerClassExclusionStrategy = new InnerClassExclusionStrategy(); modifierBasedExclusionStrategy = Gson.DEFAULT_MODIFIER_BASED_EXCLUSION_STRATEGY; excludeFieldsWithoutExposeAnnotation = false; longSerializationPolicy = LongSerializationPolicy.DEFAULT; @@ -399,7 +401,7 @@ public final class GsonBuilder { strategies.add(new VersionExclusionStrategy(ignoreVersionsAfter)); } if (excludeFieldsWithoutExposeAnnotation) { - strategies.add(new ExposeAnnotationBasedExclusionStrategy()); + strategies.add(exposeAnnotationExclusionStrategy); } ExclusionStrategy exclusionStrategy = new DisjunctionExclusionStrategy(strategies); @@ -414,9 +416,14 @@ public final class GsonBuilder { customDeserializers.registerIfAbsent(DefaultTypeAdapters.getDefaultDeserializers()); ParameterizedTypeHandlerMap> customInstanceCreators = - instanceCreators.copyOf(); + instanceCreators.copyOf(); customInstanceCreators.registerIfAbsent(DefaultTypeAdapters.getDefaultInstanceCreators()); - MappedObjectConstructor objConstructor = Gson.createObjectConstructor(customInstanceCreators); + + customSerializers.makeUnmodifiable(); + customDeserializers.makeUnmodifiable(); + instanceCreators.makeUnmodifiable(); + + MappedObjectConstructor objConstructor = new MappedObjectConstructor(customInstanceCreators); JsonFormatter formatter = prettyPrinting ? new JsonPrintFormatter(escapeHtmlChars) : new JsonCompactFormatter(escapeHtmlChars); @@ -428,18 +435,20 @@ public final class GsonBuilder { private static void addTypeAdaptersForDate(String datePattern, int dateStyle, int timeStyle, ParameterizedTypeHandlerMap> serializers, ParameterizedTypeHandlerMap> deserializers) { - // NOTE: if a date pattern exists, then that style takes priority - DefaultDateTypeAdapter dateTypeAdapter = null; - if (datePattern != null && !"".equals(datePattern.trim())) { - dateTypeAdapter = new DefaultDateTypeAdapter(datePattern); - } else if (dateStyle != DateFormat.DEFAULT && timeStyle != DateFormat.DEFAULT) { - dateTypeAdapter = new DefaultDateTypeAdapter(dateStyle, timeStyle); - } - if (dateTypeAdapter != null - && !serializers.hasSpecificHandlerFor(Date.class) + if (!serializers.hasSpecificHandlerFor(Date.class) && !deserializers.hasSpecificHandlerFor(Date.class)) { - serializers.register(Date.class, dateTypeAdapter); - deserializers.register(Date.class, dateTypeAdapter); + // NOTE: if a date pattern exists, then that style takes priority + DefaultDateTypeAdapter dateTypeAdapter = null; + if (datePattern != null && !"".equals(datePattern.trim())) { + dateTypeAdapter = new DefaultDateTypeAdapter(datePattern); + } else if (dateStyle != DateFormat.DEFAULT && timeStyle != DateFormat.DEFAULT) { + dateTypeAdapter = new DefaultDateTypeAdapter(dateStyle, timeStyle); + } + + if (dateTypeAdapter != null) { + serializers.register(Date.class, dateTypeAdapter); + deserializers.register(Date.class, dateTypeAdapter); + } } } } diff --git a/gson/src/main/java/com/google/gson/JsonTreeNavigator.java b/gson/src/main/java/com/google/gson/JsonTreeNavigator.java index dfa23f51..992de504 100644 --- a/gson/src/main/java/com/google/gson/JsonTreeNavigator.java +++ b/gson/src/main/java/com/google/gson/JsonTreeNavigator.java @@ -96,7 +96,7 @@ final class JsonTreeNavigator { if (child.isJsonNull()) { visitor.visitNullArrayMember(parent, isFirst); navigate(child); - } else if (child.isJsonArray()) { + } else if (child.isJsonArray()) { JsonArray childAsArray = child.getAsJsonArray(); visitor.visitArrayMember(parent, childAsArray, isFirst); navigate(childAsArray); diff --git a/gson/src/main/java/com/google/gson/MappedObjectConstructor.java b/gson/src/main/java/com/google/gson/MappedObjectConstructor.java index 9658639d..2136c4f8 100644 --- a/gson/src/main/java/com/google/gson/MappedObjectConstructor.java +++ b/gson/src/main/java/com/google/gson/MappedObjectConstructor.java @@ -37,8 +37,12 @@ import java.util.logging.Logger; final class MappedObjectConstructor implements ObjectConstructor { private static final Logger log = Logger.getLogger(MappedObjectConstructor.class.getName()); - private final ParameterizedTypeHandlerMap> instanceCreatorMap = - new ParameterizedTypeHandlerMap>(); + private final ParameterizedTypeHandlerMap> instanceCreatorMap; + + public MappedObjectConstructor( + ParameterizedTypeHandlerMap> instanceCreators) { + instanceCreatorMap = instanceCreators; + } @SuppressWarnings("unchecked") public T construct(Type typeOfT) { diff --git a/gson/src/main/java/com/google/gson/ObjectNavigatorFactory.java b/gson/src/main/java/com/google/gson/ObjectNavigatorFactory.java index 032f9118..37739f2b 100644 --- a/gson/src/main/java/com/google/gson/ObjectNavigatorFactory.java +++ b/gson/src/main/java/com/google/gson/ObjectNavigatorFactory.java @@ -46,18 +46,6 @@ final class ObjectNavigatorFactory { this.stack = new MemoryRefStack(); } - /** - * Creates a new {@link ObjectNavigator} for this {@code srcObject}. - * - * @see #create(Object, Type) - * @param srcObject object to navigate - * @return a new instance of a {@link ObjectNavigator} ready to navigate the - * {@code srcObject}. - */ - public ObjectNavigator create(Object srcObject) { - return create(srcObject, srcObject.getClass()); - } - /** * Creates a new {@link ObjectNavigator} for this {@code srcObject}, * {@code type} pair. diff --git a/gson/src/test/java/com/google/gson/DisjunctionExclusionStrategyTest.java b/gson/src/test/java/com/google/gson/DisjunctionExclusionStrategyTest.java index 5383e6fa..e3333af3 100644 --- a/gson/src/test/java/com/google/gson/DisjunctionExclusionStrategyTest.java +++ b/gson/src/test/java/com/google/gson/DisjunctionExclusionStrategyTest.java @@ -38,41 +38,26 @@ public class DisjunctionExclusionStrategyTest extends TestCase { private static final Field FIELD = CLAZZ.getFields()[0]; public void testBadInstantiation() throws Exception { - try { - new DisjunctionExclusionStrategy(); - } catch (IllegalArgumentException expected) { } - - try { - ExclusionStrategy[] constructorParam = null; - new DisjunctionExclusionStrategy(constructorParam); - } catch (IllegalArgumentException expected) { } - - try { - ExclusionStrategy[] constructorParam = new ExclusionStrategy[0]; - new DisjunctionExclusionStrategy(constructorParam); - } catch (IllegalArgumentException expected) { } - try { List constructorParam = null; new DisjunctionExclusionStrategy(constructorParam); } catch (IllegalArgumentException expected) { } - - try { - List constructorParam = new LinkedList(); - new DisjunctionExclusionStrategy(constructorParam); - } catch (IllegalArgumentException expected) { } } public void testSkipFieldsWithMixedTrueAndFalse() throws Exception { - DisjunctionExclusionStrategy strategy = - new DisjunctionExclusionStrategy(FALSE_STRATEGY, TRUE_STRATEGY); + List strategies = new LinkedList(); + strategies.add(FALSE_STRATEGY); + strategies.add(TRUE_STRATEGY); + DisjunctionExclusionStrategy strategy = new DisjunctionExclusionStrategy(strategies); assertTrue(strategy.shouldSkipClass(CLAZZ)); assertTrue(strategy.shouldSkipField(FIELD)); } public void testSkipFieldsWithFalseOnly() throws Exception { - DisjunctionExclusionStrategy strategy = new DisjunctionExclusionStrategy(FALSE_STRATEGY); + List strategies = new LinkedList(); + strategies.add(FALSE_STRATEGY); + DisjunctionExclusionStrategy strategy = new DisjunctionExclusionStrategy(strategies); assertFalse(strategy.shouldSkipClass(CLAZZ)); assertFalse(strategy.shouldSkipField(FIELD));