diff options
author | Teemu Suo-Anttila <teemusa@vaadin.com> | 2015-02-10 10:13:08 +0200 |
---|---|---|
committer | Vaadin Code Review <review@vaadin.com> | 2015-03-16 13:02:07 +0000 |
commit | e80f04ade51456e175e9fa7d6f8019f41fa730de (patch) | |
tree | 3e90926ca8e685a5cd37fdb159881d8fca38f33d /server/src/com/vaadin/data/RpcDataProviderExtension.java | |
parent | a4b6c9fe370f2997e24413a0db8de014105eb02a (diff) | |
download | vaadin-framework-e80f04ade51456e175e9fa7d6f8019f41fa730de.tar.gz vaadin-framework-e80f04ade51456e175e9fa7d6f8019f41fa730de.zip |
Optimise RpcDataProvider calls to container (#16642)
Change-Id: I8abaa4c1bd8eface98e42e0882cf09c92fbbf386
Diffstat (limited to 'server/src/com/vaadin/data/RpcDataProviderExtension.java')
-rw-r--r-- | server/src/com/vaadin/data/RpcDataProviderExtension.java | 119 |
1 files changed, 37 insertions, 82 deletions
diff --git a/server/src/com/vaadin/data/RpcDataProviderExtension.java b/server/src/com/vaadin/data/RpcDataProviderExtension.java index 991cb0537d..5fb0742164 100644 --- a/server/src/com/vaadin/data/RpcDataProviderExtension.java +++ b/server/src/com/vaadin/data/RpcDataProviderExtension.java @@ -85,77 +85,36 @@ public class RpcDataProviderExtension extends AbstractExtension { * doesn't leak memory. */ public class DataProviderKeyMapper implements Serializable { - private final BiMap<Integer, Object> indexToItemId = HashBiMap.create(); private final BiMap<Object, String> itemIdToKey = HashBiMap.create(); private Set<Object> pinnedItemIds = new HashSet<Object>(); - private Range activeRange = Range.withLength(0, 0); private long rollingIndex = 0; private DataProviderKeyMapper() { // private implementation } - void setActiveRange(Range newActiveRange) { - final Range[] removed = activeRange.partitionWith(newActiveRange); - final Range[] added = newActiveRange.partitionWith(activeRange); - - removeActiveRows(removed[0]); - removeActiveRows(removed[2]); - addActiveRows(added[0]); - addActiveRows(added[2]); - - activeRange = newActiveRange; - } - - private void removeActiveRows(final Range deprecated) { - for (int i = deprecated.getStart(); i < deprecated.getEnd(); i++) { - final Integer ii = Integer.valueOf(i); - final Object itemId = indexToItemId.get(ii); - - if (!isPinned(itemId)) { - itemIdToKey.remove(itemId); - indexToItemId.remove(ii); + /** + * Sets the currently active rows. This will purge any unpinned rows + * from cache. + * + * @param itemIds + * collection of itemIds to map to row keys + */ + void setActiveRows(Collection<?> itemIds) { + Set<Object> itemSet = new HashSet<Object>(itemIds); + Set<Object> itemsRemoved = new HashSet<Object>(); + for (Object itemId : itemIdToKey.keySet()) { + if (!itemSet.contains(itemId) && !isPinned(itemId)) { + itemsRemoved.add(itemId); } } - } - private void addActiveRows(Range added) { - if (added.isEmpty()) { - // Some container.getItemIds() implementations just might be - // expensive even for an empty range, so bail out early - return; + for (Object itemId : itemsRemoved) { + itemIdToKey.remove(itemId); } - List<?> newItemIds = container.getItemIds(added.getStart(), - added.length()); - Integer index = added.getStart(); - for (Object itemId : newItemIds) { - /* - * We might be in a situation we have an index <-> itemId entry - * already. This happens when something was selected, scrolled - * out of view and now we're scrolling it back into view. It's - * unnecessary to overwrite it in that case. - * - * Fun thought: considering branch prediction, it _might_ even - * be a bit faster to simply always run the code inside this - * if-state. But it sounds too stupid (and most often too - * insignificant) to try out. - */ - if (!indexToItemId.containsKey(index)) { - /* - * We might be in a situation where we have an itemId <-> - * key entry already, but no index for it. This happens when - * something that is out of view is selected - * programmatically. In that case, we only want to add an - * index for that entry, and not overwrite the key. - */ - if (!itemIdToKey.containsKey(itemId)) { - itemIdToKey.put(itemId, nextKey()); - } - - indexToItemId.forcePut(index, itemId); - } - index++; + for (Object itemId : itemSet) { + itemIdToKey.put(itemId, getKey(itemId)); } } @@ -286,11 +245,6 @@ public class RpcDataProviderExtension extends AbstractExtension { } pinnedItemIds.remove(itemId); - final Integer index = indexToItemId.inverse().get(itemId); - if (index == null || !activeRange.contains(index.intValue())) { - itemIdToKey.remove(itemId); - indexToItemId.remove(index); - } } /** @@ -303,10 +257,6 @@ public class RpcDataProviderExtension extends AbstractExtension { public boolean isPinned(Object itemId) { return pinnedItemIds.contains(itemId); } - - Object itemIdAtIndex(int index) { - return indexToItemId.get(Integer.valueOf(index)); - } } /** @@ -352,10 +302,7 @@ public class RpcDataProviderExtension extends AbstractExtension { * @param activeRowCount * the number of active rows */ - public void setActiveRows(int firstActiveRow, int activeRowCount) { - - final Range newActiveRange = Range.withLength(firstActiveRow, - activeRowCount); + public void setActiveRows(Range newActiveRange) { // TODO [[Components]] attach and detach components @@ -695,8 +642,6 @@ public class RpcDataProviderExtension extends AbstractExtension { listeners.clear(); activeRowHandler.activeRange = Range.withLength(0, 0); - keyMapper.setActiveRange(Range.withLength(0, 0)); - keyMapper.indexToItemId.clear(); /* Mark as dirty to push changes in beforeClientResponse */ bareItemSetTriggeredSizeChange = true; @@ -819,22 +764,32 @@ public class RpcDataProviderExtension extends AbstractExtension { private void pushRowData(int firstRowToPush, int numberOfRows, int firstCachedRowIndex, int cacheSize) { - Range active = Range.withLength(firstRowToPush, numberOfRows); - if (cacheSize != 0) { - Range cached = Range.withLength(firstCachedRowIndex, cacheSize); - active = active.combineWith(cached); + Range newRange = Range.withLength(firstRowToPush, numberOfRows); + Range cached = Range.withLength(firstCachedRowIndex, cacheSize); + Range fullRange = newRange; + if (!cached.isEmpty()) { + fullRange = newRange.combineWith(cached); } - keyMapper.setActiveRange(active); + List<?> itemIds = container.getItemIds(fullRange.getStart(), + fullRange.length()); + keyMapper.setActiveRows(itemIds); - List<?> itemIds = container.getItemIds(firstRowToPush, numberOfRows); JsonArray rows = Json.createArray(); - for (int i = 0; i < itemIds.size(); ++i) { - rows.set(i, getRowData(getGrid().getColumns(), itemIds.get(i))); + + // Offset the index to match the wanted range. + int diff = 0; + if (!cached.isEmpty() && newRange.getStart() > cached.getStart()) { + diff = cached.length(); + } + + for (int i = 0; i < newRange.length() && i + diff < itemIds.size(); ++i) { + Object itemId = itemIds.get(i + diff); + rows.set(i, getRowData(getGrid().getColumns(), itemId)); } rpc.setRowData(firstRowToPush, rows); - activeRowHandler.setActiveRows(active.getStart(), active.length()); + activeRowHandler.setActiveRows(fullRange); } private JsonValue getRowData(Collection<Column> columns, Object itemId) { |