diff options
3 files changed, 133 insertions, 4 deletions
diff --git a/src/com/vaadin/data/util/AbstractInMemoryContainer.java b/src/com/vaadin/data/util/AbstractInMemoryContainer.java index 3a9a0a8987..3a48d9e0de 100644 --- a/src/com/vaadin/data/util/AbstractInMemoryContainer.java +++ b/src/com/vaadin/data/util/AbstractInMemoryContainer.java @@ -722,7 +722,7 @@ public abstract class AbstractInMemoryContainer<ITEMIDTYPE, PROPERTYIDCLASS, ITE getAllItemIds().indexOf(previousItemId) + 1, newItemId, item); } - if (newItem != null) { + if (newItem != null && filter) { // TODO filter only this item, use fireItemAdded() filterAll(); if (!isFiltered()) { diff --git a/src/com/vaadin/data/util/IndexedContainer.java b/src/com/vaadin/data/util/IndexedContainer.java index 7fbb1e9128..2f45def4f1 100644 --- a/src/com/vaadin/data/util/IndexedContainer.java +++ b/src/com/vaadin/data/util/IndexedContainer.java @@ -106,8 +106,11 @@ public class IndexedContainer extends this(); if (items != null) { for (final Iterator<?> i = itemIds.iterator(); i.hasNext();) { - this.addItem(i.next()); + Object itemId = i.next(); + internalAddItemAtEnd(itemId, new IndexedContainerItem(itemId), + false); } + filterAll(); } } @@ -246,8 +249,17 @@ public class IndexedContainer extends */ @Override public Item addItem(Object itemId) { - return internalAddItemAtEnd(itemId, new IndexedContainerItem(itemId), - true); + Item item = internalAddItemAtEnd(itemId, new IndexedContainerItem( + itemId), false); + if (!isFiltered()) { + // always the last item + fireItemAdded(size() - 1, itemId, item); + } else if (passesFilters(itemId)) { + getFilteredItemIds().add(itemId); + // always the last item + fireItemAdded(size() - 1, itemId, item); + } + return item; } /** diff --git a/tests/src/com/vaadin/tests/server/container/PerformanceTestIndexedContainer.java b/tests/src/com/vaadin/tests/server/container/PerformanceTestIndexedContainer.java new file mode 100644 index 0000000000..62e6d88e72 --- /dev/null +++ b/tests/src/com/vaadin/tests/server/container/PerformanceTestIndexedContainer.java @@ -0,0 +1,117 @@ +package com.vaadin.tests.server.container; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.SortedSet; +import java.util.TreeSet; + +import junit.framework.Assert; +import junit.framework.TestCase; + +import com.vaadin.data.util.IndexedContainer; + +public class PerformanceTestIndexedContainer extends TestCase { + + private static final int REPEATS = 10; + private final static int ITEMS = 50000; + private static final long ADD_ITEM_FAIL_THRESHOLD = 200; + // TODO should improve performance of these methods + private static final long ADD_ITEM_AT_FAIL_THRESHOLD = 5000; + private static final long ADD_ITEM_AFTER_FAIL_THRESHOLD = 5000; + private static final long ADD_ITEM_AFTER_LAST_FAIL_THRESHOLD = 5000; + private static final long ADD_ITEMS_CONSTRUCTOR_FAIL_THRESHOLD = 200; + + public void testAddItemPerformance() { + Collection<Long> times = new ArrayList<Long>(); + for (int j = 0; j < REPEATS; ++j) { + IndexedContainer c = new IndexedContainer(); + long start = System.currentTimeMillis(); + for (int i = 0; i < ITEMS; i++) { + c.addItem(); + } + times.add(System.currentTimeMillis() - start); + } + checkMedian(ITEMS, times, "IndexedContainer.addItem()", + ADD_ITEM_FAIL_THRESHOLD); + } + + public void testAddItemAtPerformance() { + Collection<Long> times = new ArrayList<Long>(); + for (int j = 0; j < REPEATS; ++j) { + IndexedContainer c = new IndexedContainer(); + long start = System.currentTimeMillis(); + for (int i = 0; i < ITEMS; i++) { + c.addItemAt(0); + } + times.add(System.currentTimeMillis() - start); + } + checkMedian(ITEMS, times, "IndexedContainer.addItemAt()", + ADD_ITEM_AT_FAIL_THRESHOLD); + } + + public void testAddItemAfterPerformance() { + Object initialId = "Item0"; + Collection<Long> times = new ArrayList<Long>(); + for (int j = 0; j < REPEATS; ++j) { + IndexedContainer c = new IndexedContainer(); + c.addItem(initialId); + long start = System.currentTimeMillis(); + for (int i = 0; i < ITEMS; i++) { + c.addItemAfter(initialId); + } + times.add(System.currentTimeMillis() - start); + } + checkMedian(ITEMS, times, "IndexedContainer.addItemAfter()", + ADD_ITEM_AFTER_FAIL_THRESHOLD); + } + + public void testAddItemAfterLastPerformance() { + // TODO running with less items because slow otherwise + Collection<Long> times = new ArrayList<Long>(); + for (int j = 0; j < REPEATS; ++j) { + IndexedContainer c = new IndexedContainer(); + c.addItem(); + long start = System.currentTimeMillis(); + for (int i = 0; i < ITEMS / 3; i++) { + c.addItemAfter(c.lastItemId()); + } + times.add(System.currentTimeMillis() - start); + } + checkMedian(ITEMS / 3, times, "IndexedContainer.addItemAfter(lastId)", + ADD_ITEM_AFTER_LAST_FAIL_THRESHOLD); + } + + public void testAddItemsConstructorPerformance() { + Collection<Object> items = new ArrayList<Object>(50000); + for (int i = 0; i < ITEMS; ++i) { + items.add(new Object()); + } + + SortedSet<Long> times = new TreeSet<Long>(); + for (int j = 0; j < REPEATS; ++j) { + long start = System.currentTimeMillis(); + new IndexedContainer(items); + times.add(System.currentTimeMillis() - start); + } + checkMedian(ITEMS, times, "IndexedContainer(Collection)", + ADD_ITEMS_CONSTRUCTOR_FAIL_THRESHOLD); + } + + private void checkMedian(int items, Collection<Long> times, + String methodName, long threshold) { + long median = median(times); + System.out.println(methodName + " timings (ms) for " + items + + " items: " + times); + Assert.assertTrue(methodName + " too slow, median time " + median + + "ms for " + items + " items", median <= threshold); + } + + private Long median(Collection<Long> times) { + ArrayList<Long> list = new ArrayList<Long>(times); + Collections.sort(list); + // not exact median in some cases, but good enough + return list.get(list.size() / 2); + } + +} |