From 52db8e5457e1afcb56a5047adbddf15c44754e8c Mon Sep 17 00:00:00 2001 From: Fabian Lange Date: Thu, 3 Apr 2014 22:35:51 +0200 Subject: [PATCH] Optimizes memory and CPU usage in JSONCodec (#13545) 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 | 38 ++++++++++++++----- .../tests/server/TestClassesSerializable.java | 1 + 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/server/src/com/vaadin/server/JsonCodec.java b/server/src/com/vaadin/server/JsonCodec.java index d05922b40d..d5e1082487 100644 --- a/server/src/com/vaadin/server/JsonCodec.java +++ b/server/src/com/vaadin/server/JsonCodec.java @@ -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 getProperties(Class type) throws IntrospectionException { Collection 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) { diff --git a/server/tests/src/com/vaadin/tests/server/TestClassesSerializable.java b/server/tests/src/com/vaadin/tests/server/TestClassesSerializable.java index 0a36c7f7ce..e938a1cd37 100644 --- a/server/tests/src/com/vaadin/tests/server/TestClassesSerializable.java +++ b/server/tests/src/com/vaadin/tests/server/TestClassesSerializable.java @@ -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", // -- 2.39.5