summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAleksi Hietanen <aleksi@vaadin.com>2017-03-21 15:52:16 +0200
committerHenri Sara <henri.sara@gmail.com>2017-03-21 15:52:16 +0200
commit2dc8c1b5ad81c0dd800225b6185f47fe952251f7 (patch)
tree6e9bf954f010553ab0347e1667bf07f8a6e15ea2
parent414d5b034080b35b94bb20fc66000390818ebc24 (diff)
downloadvaadin-framework-2dc8c1b5ad81c0dd800225b6185f47fe952251f7.tar.gz
vaadin-framework-2dc8c1b5ad81c0dd800225b6185f47fe952251f7.zip
Measure TreeGrid performance (#8896)
* Update MemoryIT to report median render and request time * Add TreeGrid and TreeTable performance test UIs Addresses the collapsed cases for #8849, #8850
-rw-r--r--uitest/src/main/java/com/vaadin/tests/performance/TreeGridMemory.java67
-rw-r--r--uitest/src/main/java/com/vaadin/tests/performance/TreeTableMemory.java83
-rw-r--r--uitest/src/test/java/com/vaadin/tests/performance/MemoryIT.java64
3 files changed, 198 insertions, 16 deletions
diff --git a/uitest/src/main/java/com/vaadin/tests/performance/TreeGridMemory.java b/uitest/src/main/java/com/vaadin/tests/performance/TreeGridMemory.java
new file mode 100644
index 0000000000..105a05fe49
--- /dev/null
+++ b/uitest/src/main/java/com/vaadin/tests/performance/TreeGridMemory.java
@@ -0,0 +1,67 @@
+package com.vaadin.tests.performance;
+
+import java.util.List;
+import java.util.Optional;
+
+import javax.servlet.annotation.WebServlet;
+
+import com.vaadin.annotations.VaadinServletConfiguration;
+import com.vaadin.data.HierarchyData;
+import com.vaadin.data.provider.InMemoryHierarchicalDataProvider;
+import com.vaadin.server.VaadinServlet;
+import com.vaadin.tests.data.bean.Address;
+import com.vaadin.tests.data.bean.Person;
+import com.vaadin.ui.TreeGrid;
+
+public class TreeGridMemory extends AbstractBeansMemoryTest<TreeGrid<Person>> {
+
+ public static final String PATH = "/tree-grid-memory/";
+
+ @WebServlet(urlPatterns = PATH
+ + "*", name = "TreeGridServlet", asyncSupported = true)
+ @VaadinServletConfiguration(ui = TreeGridMemory.class, productionMode = false)
+ public static class Servlet extends VaadinServlet {
+ }
+
+ @Override
+ protected TreeGrid<Person> createComponent() {
+ TreeGrid<Person> treeGrid = new TreeGrid<>();
+ treeGrid.addColumn(Person::getFirstName).setCaption("First Name");
+ treeGrid.addColumn(Person::getLastName).setCaption("Last Name");
+ treeGrid.addColumn(person -> Optional.ofNullable(person.getAddress())
+ .map(Address::getStreetAddress).orElse(null))
+ .setCaption("Street");
+ treeGrid.addColumn(person -> Optional.ofNullable(person.getAddress())
+ .map(Address::getPostalCode).map(Object::toString).orElse(""))
+ .setCaption("Zip");
+ treeGrid.addColumn(person -> Optional.ofNullable(person.getAddress())
+ .map(Address::getCity).orElse(null)).setCaption("City");
+ return treeGrid;
+ }
+
+ @Override
+ protected void setInMemoryContainer(TreeGrid<Person> treeGrid,
+ List<Person> data) {
+ HierarchyData<Person> hierarchyData = new HierarchyData<>();
+ if (data.size() % 2 == 0) {
+ // treat list as if it were a balanced binary tree
+ hierarchyData.addItem(null, data.get(0));
+ int n = 0;
+ while (2 * n + 2 < data.size()) {
+ hierarchyData.addItems(data.get(n),
+ data.subList(2 * n + 1, 2 * n + 3));
+ n++;
+ }
+ } else {
+ hierarchyData.addItems(null, data);
+ }
+ treeGrid.setDataProvider(
+ new InMemoryHierarchicalDataProvider<>(hierarchyData));
+ }
+
+ @Override
+ protected void setBackendContainer(TreeGrid<Person> component,
+ List<Person> data) {
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/uitest/src/main/java/com/vaadin/tests/performance/TreeTableMemory.java b/uitest/src/main/java/com/vaadin/tests/performance/TreeTableMemory.java
new file mode 100644
index 0000000000..203c74fd4d
--- /dev/null
+++ b/uitest/src/main/java/com/vaadin/tests/performance/TreeTableMemory.java
@@ -0,0 +1,83 @@
+package com.vaadin.tests.performance;
+
+import java.util.List;
+import java.util.Optional;
+
+import javax.servlet.annotation.WebServlet;
+
+import com.vaadin.annotations.VaadinServletConfiguration;
+import com.vaadin.server.VaadinServlet;
+import com.vaadin.tests.data.bean.Address;
+import com.vaadin.tests.data.bean.Person;
+import com.vaadin.v7.data.Item;
+import com.vaadin.v7.data.util.HierarchicalContainer;
+import com.vaadin.v7.ui.TreeTable;
+
+public class TreeTableMemory extends AbstractBeansMemoryTest<TreeTable> {
+
+ public static final String PATH = "/tree-table-memory/";
+
+ @WebServlet(urlPatterns = PATH
+ + "*", name = "TreeTableServlet", asyncSupported = true)
+ @VaadinServletConfiguration(ui = TreeTableMemory.class, productionMode = false, widgetset = "com.vaadin.v7.Vaadin7WidgetSet")
+ public static class Servlet extends VaadinServlet {
+ }
+
+ @Override
+ protected TreeTable createComponent() {
+ TreeTable treeTable = new TreeTable();
+ return treeTable;
+ }
+
+ @Override
+ protected void setInMemoryContainer(TreeTable treeTable,
+ List<Person> data) {
+ HierarchicalContainer container = new HierarchicalContainer();
+ container.addContainerProperty("firstName", String.class, null);
+ container.addContainerProperty("lastName", String.class, null);
+ container.addContainerProperty("street", String.class, null);
+ container.addContainerProperty("zip", String.class, null);
+ container.addContainerProperty("city", String.class, null);
+
+ if (data.size() % 2 == 0) {
+ createItem(0, container, data);
+ int n = 0;
+ while (2 * n + 2 < data.size()) {
+ for (int i : new Integer[] { 1, 2 }) {
+ createItem(2 * n + i, container, data);
+ container.setParent(2 * n + i, n);
+ }
+ n++;
+ }
+ } else {
+ for (int i = 0; i < data.size(); i++) {
+ createItem(i, container, data);
+ }
+ }
+ treeTable.setContainerDataSource(container);
+ }
+
+ private void createItem(int index, HierarchicalContainer container,
+ List<Person> data) {
+ Item item = container.addItem(index);
+ item.getItemProperty("firstName")
+ .setValue(data.get(index).getFirstName());
+ item.getItemProperty("lastName")
+ .setValue(data.get(index).getLastName());
+ item.getItemProperty("street")
+ .setValue(Optional.ofNullable(data.get(index).getAddress())
+ .map(Address::getStreetAddress).orElse(null));
+ item.getItemProperty("zip")
+ .setValue(Optional.ofNullable(data.get(index).getAddress())
+ .map(Address::getPostalCode).map(Object::toString)
+ .orElse(""));
+ item.getItemProperty("city")
+ .setValue(Optional.ofNullable(data.get(index).getAddress())
+ .map(Address::getCity).orElse(null));
+ }
+
+ @Override
+ protected void setBackendContainer(TreeTable component, List<Person> data) {
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/uitest/src/test/java/com/vaadin/tests/performance/MemoryIT.java b/uitest/src/test/java/com/vaadin/tests/performance/MemoryIT.java
index 4ac3ae68ff..0f4249b6ea 100644
--- a/uitest/src/test/java/com/vaadin/tests/performance/MemoryIT.java
+++ b/uitest/src/test/java/com/vaadin/tests/performance/MemoryIT.java
@@ -15,6 +15,9 @@
*/
package com.vaadin.tests.performance;
+import java.util.ArrayList;
+import java.util.List;
+
import org.apache.commons.lang3.StringUtils;
import org.junit.Assert;
import org.junit.Test;
@@ -27,29 +30,40 @@ import com.vaadin.tests.tb3.SingleBrowserTest;
@Category(MeasurementTest.class)
public class MemoryIT extends SingleBrowserTest {
+ private static final int MAX_ITERATIONS = 20;
+
@Test
public void measureMemory() {
- printTeamcityStats("grid-v8-one-item-size",
- getGridSize(GridMemory.PATH, 1));
- printTeamcityStats("grid-v7-one-item-size",
- getGridSize(CompatibilityGridMemory.PATH, 1));
-
- printTeamcityStats("grid-v8-100thousand-items-size",
- getGridSize(GridMemory.PATH, 100000));
- printTeamcityStats("grid-v7-100thousand-items-size",
- getGridSize(CompatibilityGridMemory.PATH, 100000));
+ performTest(GridMemory.PATH, 1, "grid-v8-one-item-");
+ performTest(CompatibilityGridMemory.PATH, 1, "grid-v7-one-item-");
+
+ performTest(GridMemory.PATH, 100000, "grid-v8-100thousand-items-");
+ performTest(CompatibilityGridMemory.PATH, 100000,
+ "grid-v7-100thousand-items-");
+
+ performTest(TreeGridMemory.PATH, 1, "tree-grid-one-item-");
+ performTest(TreeTableMemory.PATH, 1, "tree-table-one-item-");
+
+ performTest(TreeGridMemory.PATH, 100000,
+ "tree-grid-100thousand-items-");
+ performTest(TreeTableMemory.PATH, 100000,
+ "tree-table-100thousand-items-");
}
@Override
protected void closeApplication() {
}
- private long getGridSize(String path, int itemsCount) {
- // Repeat until we get consecutive results within 0.1% of each other
+ private void performTest(String path, int itemsCount,
+ String teamcityStatPrefix) {
double lastResult = 0;
int stableNumber = 0;
- for (int i = 0; i < 500; i++) {
+ List<Long> renderingTimes = new ArrayList<>();
+ List<Long> requestTimes = new ArrayList<>();
+ for (int i = 0; i < MAX_ITERATIONS; i++) {
openUI(path, itemsCount);
+ renderingTimes.add(testBench().totalTimeSpentRendering());
+ requestTimes.add(testBench().totalTimeSpentServicingRequests());
long currentResult = Long
.parseLong(findElement(By.id("memory")).getText());
close();
@@ -59,12 +73,29 @@ public class MemoryIT extends SingleBrowserTest {
}
lastResult = currentResult;
if (stableNumber == 5) {
- return currentResult;
+ System.out.println(
+ "Memory usage stabilized after " + i + " iterations");
+ printTeamcityStats(teamcityStatPrefix + "size", currentResult);
+ printTeamcityStats(teamcityStatPrefix + "rendering-time",
+ median(renderingTimes));
+ printTeamcityStats(teamcityStatPrefix + "request-time",
+ median(requestTimes));
+ return;
+ }
+ if (i == MAX_ITERATIONS) {
+ Assert.fail("Memory size does not stabilize");
}
}
+ }
- Assert.fail("Memory size does not stabilize");
- return -1;
+ private long median(List<Long> values) {
+ values.sort(Long::compareTo);
+ int middle = values.size() / 2;
+ if (values.size() % 2 == 1) {
+ return values.get(middle);
+ } else {
+ return (values.get(middle - 1) + values.get(middle)) / 2;
+ }
}
private boolean approx(double num1, double num2, double epsilon) {
@@ -76,7 +107,8 @@ public class MemoryIT extends SingleBrowserTest {
private void openUI(String path, int itemsNumber) {
getDriver().get(StringUtils.strip(getBaseURL(), "/") + path + "?items="
+ itemsNumber);
- Assert.assertTrue(isElementPresent(By.className("v-grid")));
+ Assert.assertTrue(isElementPresent(By.className("v-grid"))
+ || isElementPresent(By.className("v-table")));
}
private void close() {