Browse Source

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
tags/8.1.0.alpha2
Aleksi Hietanen 7 years ago
parent
commit
2dc8c1b5ad

+ 67
- 0
uitest/src/main/java/com/vaadin/tests/performance/TreeGridMemory.java View File

@@ -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();
}
}

+ 83
- 0
uitest/src/main/java/com/vaadin/tests/performance/TreeTableMemory.java View File

@@ -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();
}
}

+ 48
- 16
uitest/src/test/java/com/vaadin/tests/performance/MemoryIT.java View File

@@ -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() {

Loading…
Cancel
Save