You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

AbstractBeansMemoryTest.java 7.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. /*
  2. * Copyright 2000-2016 Vaadin Ltd.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License"); you may not
  5. * use this file except in compliance with the License. You may obtain a copy of
  6. * the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  12. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  13. * License for the specific language governing permissions and limitations under
  14. * the License.
  15. */
  16. package com.vaadin.tests.performance;
  17. import java.lang.reflect.Field;
  18. import java.math.BigDecimal;
  19. import java.util.Collections;
  20. import java.util.Date;
  21. import java.util.List;
  22. import java.util.Random;
  23. import java.util.stream.Collectors;
  24. import java.util.stream.IntStream;
  25. import com.vaadin.server.VaadinRequest;
  26. import com.vaadin.tests.data.bean.Address;
  27. import com.vaadin.tests.data.bean.Country;
  28. import com.vaadin.tests.data.bean.Person;
  29. import com.vaadin.tests.data.bean.Sex;
  30. import com.vaadin.ui.AbstractComponent;
  31. import com.vaadin.ui.Button;
  32. import com.vaadin.ui.Component;
  33. import com.vaadin.ui.HasComponents;
  34. import com.vaadin.ui.Label;
  35. import com.vaadin.ui.MenuBar;
  36. import com.vaadin.ui.MenuBar.MenuItem;
  37. import com.vaadin.ui.UI;
  38. import com.vaadin.ui.VerticalLayout;
  39. import jdk.nashorn.internal.ir.debug.ObjectSizeCalculator;
  40. /**
  41. * @author Vaadin Ltd
  42. *
  43. */
  44. public abstract class AbstractBeansMemoryTest<T extends AbstractComponent>
  45. extends UI {
  46. private int dataSize;
  47. private boolean isInMemory;
  48. private boolean isDataOnly;
  49. private Label logLabel;
  50. private Label memoryLabel;
  51. @Override
  52. protected void init(VaadinRequest request) {
  53. String items = request.getParameter("items");
  54. int itemsCount = 1;
  55. if (items != null) {
  56. itemsCount = Integer.parseInt(items);
  57. }
  58. VerticalLayout layout = new VerticalLayout();
  59. setContent(layout);
  60. layout.addComponent(new Label(getClass().getSimpleName()));
  61. memoryLabel = new Label();
  62. memoryLabel.setId("memory");
  63. layout.addComponent(memoryLabel);
  64. logLabel = new Label();
  65. logLabel.setId("log");
  66. layout.addComponent(logLabel);
  67. T component = createComponent();
  68. setData(null, itemsCount, component, true);
  69. layout.addComponent(createMenu(component));
  70. layout.addComponent(component);
  71. Button close = new Button("Close UI", event -> close());
  72. close.setId("close");
  73. layout.addComponent(close);
  74. }
  75. protected abstract T createComponent();
  76. private Random random = new Random();
  77. protected List<Person> createBeans(int size) {
  78. return IntStream.range(0, size).mapToObj(this::createPerson)
  79. .collect(Collectors.toList());
  80. }
  81. protected Person createPerson(int index) {
  82. random.setSeed(index);
  83. Person person = new Person();
  84. person.setFirstName("First Name " + random.nextInt());
  85. person.setLastName("Last Name " + random.nextInt());
  86. person.setAge(random.nextInt());
  87. person.setBirthDate(new Date(random.nextLong()));
  88. person.setDeceased(random.nextBoolean());
  89. person.setEmail(random.nextInt() + "user@example.com");
  90. person.setRent(new BigDecimal(random.nextLong()));
  91. person.setSalary(random.nextInt());
  92. person.setSalaryDouble(random.nextDouble());
  93. person.setSex(Sex.values()[random.nextInt(Sex.values().length)]);
  94. Address address = new Address();
  95. person.setAddress(address);
  96. address.setCity("city " + random.nextInt());
  97. address.setPostalCode(random.nextInt());
  98. address.setStreetAddress("street address " + random.nextInt());
  99. address.setCountry(
  100. Country.values()[random.nextInt(Country.values().length)]);
  101. return person;
  102. }
  103. protected abstract void setInMemoryContainer(T component,
  104. List<Person> data);
  105. protected abstract void setBackendContainer(T component, List<Person> data);
  106. @Override
  107. public VerticalLayout getContent() {
  108. return (VerticalLayout) super.getContent();
  109. }
  110. @SuppressWarnings("restriction")
  111. private void setData(MenuItem item, int size, T component,
  112. boolean memoryContainer) {
  113. if (item != null) {
  114. MenuItem parent = item.getParent();
  115. parent.getChildren().stream().filter(itm -> !itm.equals(item))
  116. .forEach(itm -> itm.setChecked(false));
  117. logLabel.setValue(item.getText());
  118. }
  119. dataSize = size;
  120. isInMemory = memoryContainer;
  121. List<Person> persons = createBeans(size);
  122. if (isDataOnly) {
  123. component.setData(persons);
  124. persons = Collections.emptyList();
  125. } else {
  126. component.setData(null);
  127. }
  128. if (isInMemory) {
  129. setInMemoryContainer(component, persons);
  130. } else {
  131. setBackendContainer(component, persons);
  132. }
  133. HasComponents container = component.getParent();
  134. setParent(component, null);
  135. memoryLabel.setValue(
  136. String.valueOf(ObjectSizeCalculator.getObjectSize(component)));
  137. setParent(component, container);
  138. }
  139. private void setParent(Component component, Component parent) {
  140. try {
  141. Field field = AbstractComponent.class.getDeclaredField("parent");
  142. field.setAccessible(true);
  143. field.set(component, parent);
  144. } catch (NoSuchFieldException | SecurityException
  145. | IllegalArgumentException | IllegalAccessException e) {
  146. throw new RuntimeException(e);
  147. }
  148. }
  149. private Component createMenu(T component) {
  150. MenuBar menu = new MenuBar();
  151. createContainerSizeMenu(menu.addItem("Size", null), component);
  152. createContainerMenu(menu.addItem("Data provider", null), component);
  153. menu.addItem("Create only data",
  154. item -> toggleDataOnly(item, component)).setCheckable(true);
  155. return menu;
  156. }
  157. private void toggleDataOnly(MenuItem item, T component) {
  158. isDataOnly = item.isChecked();
  159. setData(null, dataSize, component, isInMemory);
  160. }
  161. private void createContainerMenu(MenuItem menu, T component) {
  162. MenuItem menuItem = menu.addItem("Use in-memory container",
  163. item -> setData(item, dataSize, component, true));
  164. menuItem.setCheckable(true);
  165. menuItem.setChecked(true);
  166. menuItem = menu.addItem("Use backend container",
  167. item -> setData(item, dataSize, component, false));
  168. menuItem.setCheckable(true);
  169. }
  170. private void createContainerSizeMenu(MenuItem menu, T component) {
  171. List<MenuItem> items = IntStream.of(1, 10000, 100000, 500000, 1000000)
  172. .mapToObj(size -> addContainerSizeMenu(size, menu, component))
  173. .collect(Collectors.toList());
  174. if (dataSize == 1) {
  175. items.get(0).setChecked(true);
  176. }
  177. }
  178. private MenuItem addContainerSizeMenu(int size, MenuItem menu,
  179. T component) {
  180. MenuItem item = menu.addItem("Set data provider size to " + size,
  181. itm -> setData(itm, size, component, isInMemory));
  182. item.setCheckable(true);
  183. return item;
  184. }
  185. }