]> source.dussan.org Git - vaadin-framework.git/commitdiff
Optimizes memory and CPU usage in JSONCodec (#13545)
authorFabian Lange <lange.fabian@gmail.com>
Thu, 3 Apr 2014 20:35:51 +0000 (22:35 +0200)
committerFabian Lange <lange.fabian@gmail.com>
Wed, 9 Apr 2014 09:47:21 +0000 (11:47 +0200)
The null element and the empty JSONArray are frequently created and used
as temporary objects to be encoded by the json encoder. Because they are
never manipulated it is possible to reuse the same empty element again
and save a significant amount of temp objects.
This also helps jsonEquals, which then can return faster due to:
if (fieldValue == referenceValue) return true

jsonEquals does not need to check the referenceValue for JSONobject.NULL.
The invoking code makes sure this never happens.
Boolean and Integer values are very often and much more efficiently
compared directly instead of using toString.

Change-Id: I5fd736427019406469357cda1115d2683b7a5e2b

server/src/com/vaadin/server/JsonCodec.java
server/tests/src/com/vaadin/tests/server/TestClassesSerializable.java

index d05922b40d47729955fc12d2dad3950cdaa14fe9..d5e1082487facab9ef0cfa3662868195908d0e0c 100644 (file)
@@ -62,6 +62,25 @@ import com.vaadin.ui.ConnectorTracker;
  */
 public class JsonCodec implements Serializable {
 
+    /* Immutable Encode Result representing null */
+    private static final EncodeResult ENCODE_RESULT_NULL = new EncodeResult(
+            JSONObject.NULL);
+
+    /* Immutable empty JSONArray */
+    private static final JSONArray EMPTY_JSON_ARRAY = new JSONArray() {
+        @Override
+        public JSONArray put(Object value) {
+            throw new UnsupportedOperationException(
+                    "Immutable empty JSONArray.");
+        };
+
+        @Override
+        public JSONArray put(int index, Object value) {
+            throw new UnsupportedOperationException(
+                    "Immutable empty JSONArray.");
+        };
+    };
+
     public static interface BeanProperty extends Serializable {
         public Object getValue(Object bean) throws Exception;
 
@@ -635,7 +654,7 @@ public class JsonCodec implements Serializable {
         }
 
         if (null == value) {
-            return encodeNull();
+            return ENCODE_RESULT_NULL;
         }
 
         if (value instanceof String[]) {
@@ -680,7 +699,7 @@ public class JsonCodec implements Serializable {
             if (value instanceof Component
                     && !(LegacyCommunicationManager
                             .isComponentVisibleToClient((Component) value))) {
-                return encodeNull();
+                return ENCODE_RESULT_NULL;
             }
             return new EncodeResult(connector.getConnectorId());
         } else if (value instanceof Enum) {
@@ -701,10 +720,6 @@ public class JsonCodec implements Serializable {
         }
     }
 
-    private static EncodeResult encodeNull() {
-        return new EncodeResult(JSONObject.NULL);
-    }
-
     public static Collection<BeanProperty> getProperties(Class<?> type)
             throws IntrospectionException {
         Collection<BeanProperty> cachedProperties = typePropertyCache.get(type);
@@ -781,14 +796,17 @@ public class JsonCodec implements Serializable {
         if (fieldValue == JSONObject.NULL) {
             fieldValue = null;
         }
-        if (referenceValue == JSONObject.NULL) {
-            referenceValue = null;
-        }
 
         if (fieldValue == referenceValue) {
             return true;
         } else if (fieldValue == null || referenceValue == null) {
             return false;
+        } else if (fieldValue instanceof Integer
+                && referenceValue instanceof Integer) {
+            return ((Integer) fieldValue).equals(referenceValue);
+        } else if (fieldValue instanceof Boolean
+                && referenceValue instanceof Boolean) {
+            return ((Boolean) fieldValue).equals(referenceValue);
         } else {
             return fieldValue.toString().equals(referenceValue.toString());
         }
@@ -849,7 +867,7 @@ public class JsonCodec implements Serializable {
         if (map.isEmpty()) {
             // Client -> server encodes empty map as an empty array because of
             // #8906. Do the same for server -> client to maintain symmetry.
-            return new JSONArray();
+            return EMPTY_JSON_ARRAY;
         }
 
         if (keyType == String.class) {
index 0a36c7f7ce939c0fa152b4eb1584a0967d53c2cd..e938a1cd37a2a9f259b485714f8b9a2aa5aca7bc 100644 (file)
@@ -63,6 +63,7 @@ public class TestClassesSerializable extends TestCase {
             "com\\.vaadin\\.sass.*", //
             "com\\.vaadin\\.testbench.*", //
             "com\\.vaadin\\.util\\.CurrentInstance\\$1", //
+            "com\\.vaadin\\.server\\.JsonCodec\\$1", //
             "com\\.vaadin\\.server\\.communication\\.PushConnection", //
             "com\\.vaadin\\.server\\.communication\\.AtmospherePushConnection", //
             "com\\.vaadin\\.util\\.ConnectorHelper", //