summaryrefslogtreecommitdiffstats
path: root/client
diff options
context:
space:
mode:
authorHenri Sara <hesara@vaadin.com>2013-08-22 11:03:47 +0300
committerVaadin Code Review <review@vaadin.com>2013-08-22 08:57:09 +0000
commitfac9ff6dfe51b9e858fedf7816bb02bca615e19a (patch)
tree8b3fcd04f552b652367cae8a48b7335c85c9c6b5 /client
parentc7a8c3f60912db10b00ad735416cc3df1fb5ffba (diff)
downloadvaadin-framework-fac9ff6dfe51b9e858fedf7816bb02bca615e19a.tar.gz
vaadin-framework-fac9ff6dfe51b9e858fedf7816bb02bca615e19a.zip
Optimize resetting of state when detaching components (#10899, #11284)
This has a significant impact on some older browsers, especially IE8. This change also adds hierarchy update profiling statements to help find hotspots. Change-Id: Id7025776f8606794ba1d7aef99e2c37832b0c6bb
Diffstat (limited to 'client')
-rw-r--r--client/src/com/vaadin/client/ApplicationConnection.java70
1 files changed, 61 insertions, 9 deletions
diff --git a/client/src/com/vaadin/client/ApplicationConnection.java b/client/src/com/vaadin/client/ApplicationConnection.java
index 0b64f56c3e..dc3378560e 100644
--- a/client/src/com/vaadin/client/ApplicationConnection.java
+++ b/client/src/com/vaadin/client/ApplicationConnection.java
@@ -1701,7 +1701,9 @@ public class ApplicationConnection {
// hierarchy, unregister it and any possible
// children. The UIConnector should never be
// unregistered even though it has no parent.
+ Profiler.enter("unregisterRemovedConnectors unregisterConnector");
connectorMap.unregisterConnector(c);
+ Profiler.leave("unregisterRemovedConnectors unregisterConnector");
unregistered++;
}
@@ -1984,6 +1986,8 @@ public class ApplicationConnection {
JsArrayString hierarchyKeys = hierarchies.getKeyArray();
for (int i = 0; i < hierarchyKeys.length(); i++) {
try {
+ Profiler.enter("updateConnectorHierarchy hierarchy entry");
+
String connectorId = hierarchyKeys.get(i);
ServerConnector parentConnector = connectorMap
.getConnector(connectorId);
@@ -1991,6 +1995,8 @@ public class ApplicationConnection {
.getJSStringArray(connectorId);
int childConnectorSize = childConnectorIds.length();
+ Profiler.enter("updateConnectorHierarchy find new connectors");
+
List<ServerConnector> newChildren = new ArrayList<ServerConnector>();
List<ComponentConnector> newComponents = new ArrayList<ComponentConnector>();
for (int connectorIndex = 0; connectorIndex < childConnectorSize; connectorIndex++) {
@@ -2029,6 +2035,8 @@ public class ApplicationConnection {
}
}
+ Profiler.leave("updateConnectorHierarchy find new connectors");
+
// TODO This check should be done on the server side in
// the future so the hierarchy update is only sent when
// something actually has changed
@@ -2041,6 +2049,8 @@ public class ApplicationConnection {
continue;
}
+ Profiler.enter("updateConnectorHierarchy handle HasComponentsConnector");
+
if (parentConnector instanceof HasComponentsConnector) {
HasComponentsConnector ccc = (HasComponentsConnector) parentConnector;
List<ComponentConnector> oldComponents = ccc
@@ -2062,7 +2072,13 @@ public class ApplicationConnection {
+ " has component children even though it isn't a HasComponentsConnector");
}
+ Profiler.leave("updateConnectorHierarchy handle HasComponentsConnector");
+
+ Profiler.enter("updateConnectorHierarchy setChildren");
parentConnector.setChildren(newChildren);
+ Profiler.leave("updateConnectorHierarchy setChildren");
+
+ Profiler.enter("updateConnectorHierarchy find removed children");
/*
* Find children removed from this parent and mark for
@@ -2084,11 +2100,17 @@ public class ApplicationConnection {
maybeDetached.add(oldChild.getConnectorId());
}
}
+
+ Profiler.leave("updateConnectorHierarchy find removed children");
} catch (final Throwable e) {
VConsole.error(e);
+ } finally {
+ Profiler.leave("updateConnectorHierarchy hierarchy entry");
}
}
+ Profiler.enter("updateConnectorHierarchy detach removed connectors");
+
/*
* Connector is in maybeDetached at this point if it has been
* removed from its parent but not added to any other parent
@@ -2100,6 +2122,8 @@ public class ApplicationConnection {
recursivelyDetach(removed, result.events);
}
+ Profiler.leave("updateConnectorHierarchy detach removed connectors");
+
Profiler.leave("updateConnectorHierarchy");
return result;
@@ -2116,27 +2140,44 @@ public class ApplicationConnection {
* is the closest we can get without data from the server.
* #10151
*/
+ Profiler.enter("ApplicationConnection recursivelyDetach reset state");
try {
+ Profiler.enter("ApplicationConnection recursivelyDetach reset state - getStateType");
Type stateType = AbstractConnector.getStateType(connector);
+ Profiler.leave("ApplicationConnection recursivelyDetach reset state - getStateType");
// Empty state instance to get default property values from
+ Profiler.enter("ApplicationConnection recursivelyDetach reset state - createInstance");
Object defaultState = stateType.createInstance();
+ Profiler.leave("ApplicationConnection recursivelyDetach reset state - createInstance");
- SharedState state = connector.getState();
-
- JsArrayObject<Property> properties = stateType
- .getPropertiesAsArray();
- int size = properties.size();
- for (int i = 0; i < size; i++) {
- Property property = properties.get(i);
- property.setValue(state,
- property.getValue(defaultState));
+ if (connector instanceof AbstractConnector) {
+ // optimization as the loop setting properties is very
+ // slow, especially on IE8
+ replaceState((AbstractConnector) connector,
+ defaultState);
+ } else {
+ SharedState state = connector.getState();
+
+ Profiler.enter("ApplicationConnection recursivelyDetach reset state - properties");
+ JsArrayObject<Property> properties = stateType
+ .getPropertiesAsArray();
+ int size = properties.size();
+ for (int i = 0; i < size; i++) {
+ Property property = properties.get(i);
+ property.setValue(state,
+ property.getValue(defaultState));
+ }
+ Profiler.leave("ApplicationConnection recursivelyDetach reset state - properties");
}
} catch (NoDataException e) {
throw new RuntimeException("Can't reset state for "
+ Util.getConnectorString(connector), e);
+ } finally {
+ Profiler.leave("ApplicationConnection recursivelyDetach reset state");
}
+ Profiler.enter("ApplicationConnection recursivelyDetach perform detach");
/*
* Recursively detach children to make sure they get
* setParent(null) and hierarchy change events as needed.
@@ -2153,18 +2194,22 @@ public class ApplicationConnection {
}
recursivelyDetach(child, events);
}
+ Profiler.leave("ApplicationConnection recursivelyDetach perform detach");
/*
* Clear child list and parent
*/
+ Profiler.enter("ApplicationConnection recursivelyDetach clear children and parent");
connector
.setChildren(Collections.<ServerConnector> emptyList());
connector.setParent(null);
+ Profiler.leave("ApplicationConnection recursivelyDetach clear children and parent");
/*
* Create an artificial hierarchy event for containers to give
* it a chance to clean up after its children if it has any
*/
+ Profiler.enter("ApplicationConnection recursivelyDetach create hierarchy event");
if (connector instanceof HasComponentsConnector) {
HasComponentsConnector ccc = (HasComponentsConnector) connector;
List<ComponentConnector> oldChildren = ccc
@@ -2185,8 +2230,15 @@ public class ApplicationConnection {
events.add(event);
}
}
+ Profiler.leave("ApplicationConnection recursivelyDetach create hierarchy event");
}
+ private native void replaceState(AbstractConnector connector,
+ Object defaultState)
+ /*-{
+ connector.@com.vaadin.client.ui.AbstractConnector::state = defaultState;
+ }-*/;
+
private void handleRpcInvocations(ValueMap json) {
if (json.containsKey("rpc")) {
Profiler.enter("handleRpcInvocations");