#115297: Speeding up setPairs(theSameType) by use of LinkedHashSet instead of ArrayList
1.1 --- a/openide.util/src/org/openide/util/lookup/AbstractLookup.java Thu Sep 13 07:59:50 2007 +0000
1.2 +++ b/openide.util/src/org/openide/util/lookup/AbstractLookup.java Thu Sep 13 16:19:36 2007 +0000
1.3 @@ -26,10 +26,21 @@
1.4 import java.io.ObjectOutputStream;
1.5 import java.io.Serializable;
1.6
1.7 -import java.lang.ref.*;
1.8 import java.lang.ref.ReferenceQueue;
1.9 +import java.lang.ref.WeakReference;
1.10 +import java.util.ArrayList;
1.11 +import java.util.Arrays;
1.12 +import java.util.Collection;
1.13 +import java.util.Collections;
1.14 +import java.util.Enumeration;
1.15 +import java.util.HashMap;
1.16 +import java.util.HashSet;
1.17 +import java.util.Iterator;
1.18 +import java.util.LinkedHashSet;
1.19 +import java.util.Map;
1.20 +import java.util.Set;
1.21 +import java.util.TreeSet;
1.22
1.23 -import java.util.*;
1.24 import org.openide.util.Utilities;
1.25
1.26
1.27 @@ -88,6 +99,7 @@
1.28 protected AbstractLookup() {
1.29 }
1.30
1.31 + @Override
1.32 public String toString() {
1.33 if (tree instanceof Storage) {
1.34 return "AbstractLookup" + lookup(new Lookup.Template<Object>(Object.class)).allItems(); // NOI18N
1.35 @@ -344,6 +356,7 @@
1.36 return (item == null) ? null : item.getInstance();
1.37 }
1.38
1.39 + @Override
1.40 public final <T> Lookup.Item<T> lookupItem(Lookup.Template<T> template) {
1.41 AbstractLookup.this.beforeLookup(template);
1.42
1.43 @@ -910,6 +923,7 @@
1.44 /** Set of all classes.
1.45 *
1.46 */
1.47 + @Override
1.48 public Set<Class<? extends T>> allClasses() {
1.49 reference.lookup.beforeLookup(reference.template);
1.50
1.51 @@ -937,6 +951,7 @@
1.52
1.53 /** Items are stored directly in the allItems.
1.54 */
1.55 + @Override
1.56 public Collection<? extends Item<T>> allItems() {
1.57 reference.lookup.beforeLookup(reference.template);
1.58
1.59 @@ -1022,6 +1037,7 @@
1.60 return obj == this;
1.61 }
1.62 */
1.63 + @Override
1.64 public String toString() {
1.65 return super.toString() + " for " + reference.template;
1.66 }
1.67 @@ -1050,13 +1066,10 @@
1.68 this.al = al;
1.69
1.70 if (earlyPairs != null) {
1.71 - // we must just add no override!
1.72 - for (Pair<?> p : earlyPairs) {
1.73 - addPair(p);
1.74 - }
1.75 + ArrayList<Pair> ep = earlyPairs;
1.76 + earlyPairs = null;
1.77 + setPairs(ep);
1.78 }
1.79 -
1.80 - earlyPairs = null;
1.81 } else {
1.82 throw new IllegalStateException(
1.83 "Trying to use content for " + al + " but it is already used for " + this.al
1.84 @@ -1269,6 +1282,8 @@
1.85 * @author Jaroslav Tulach
1.86 */
1.87 static final class ISE extends IllegalStateException {
1.88 + static final long serialVersionUID = 100L;
1.89 +
1.90 /** list of jobs to execute. */
1.91 private java.util.List<Job> jobs;
1.92
2.1 --- a/openide.util/src/org/openide/util/lookup/InheritanceTree.java Thu Sep 13 07:59:50 2007 +0000
2.2 +++ b/openide.util/src/org/openide/util/lookup/InheritanceTree.java Thu Sep 13 16:19:36 2007 +0000
2.3 @@ -1062,7 +1062,7 @@
2.4 public ArrayList<Node> children;
2.5
2.6 /** list of items assigned to this node (suspect to be subclasses) */
2.7 - public List<Pair> items;
2.8 + public Collection<Pair> items;
2.9
2.10 /** Constructor.
2.11 */
2.12 @@ -1074,14 +1074,14 @@
2.13 * @return true if so.
2.14 */
2.15 public boolean deserialized() {
2.16 - if ((items == null) || items instanceof ArrayList) {
2.17 + if ((items == null) || items instanceof LinkedHashSet) {
2.18 return false;
2.19 }
2.20
2.21 if (items.isEmpty()) {
2.22 items = null;
2.23 } else {
2.24 - items = new ArrayList<Pair>(items);
2.25 + items = new LinkedHashSet<Pair>(items);
2.26 }
2.27
2.28 return true;
2.29 @@ -1093,7 +1093,7 @@
2.30 if (items == null || items == Collections.EMPTY_LIST) {
2.31 items = Collections.emptyList();
2.32 } else {
2.33 - items = Collections.synchronizedList(items);
2.34 + items = Collections.synchronizedCollection(items);
2.35 }
2.36 }
2.37
2.38 @@ -1133,22 +1133,28 @@
2.39 */
2.40 public boolean assignItem(InheritanceTree tree, AbstractLookup.Pair<?> item) {
2.41 if ((items == null) || (items == Collections.EMPTY_LIST)) {
2.42 - items = new ArrayList<Pair>();
2.43 + items = new LinkedHashSet<Pair>();
2.44 items.add(item);
2.45
2.46 return true;
2.47 }
2.48
2.49 if (items.contains(item)) {
2.50 - int i = items.indexOf(item);
2.51 - AbstractLookup.Pair old = items.get(i);
2.52 + Iterator<Pair> it = items.iterator();
2.53 + Pair old;
2.54 + for (;;) {
2.55 + old = it.next();
2.56 + if (item.equals(old)) {
2.57 + break;
2.58 + }
2.59 + }
2.60
2.61 if (old != item) {
2.62 // replace the items there
2.63 item.setIndex(tree, old.getIndex());
2.64 }
2.65
2.66 - items.remove(old);
2.67 + it.remove();
2.68 items.add(item);
2.69
2.70 return false;
2.71 @@ -1175,16 +1181,16 @@
2.72 private String clazzName;
2.73 private transient Class<?> clazz;
2.74 private ArrayList<Node> children;
2.75 - private ArrayList<Pair> items;
2.76 + private Collection<Pair> items;
2.77
2.78 public R(Node n) {
2.79 this.clazzName = n.getType().getName();
2.80 this.children = n.children;
2.81
2.82 - if (n.items instanceof ArrayList || (n.items == null)) {
2.83 - this.items = (ArrayList<Pair>) n.items;
2.84 + if (n.items instanceof LinkedHashSet || (n.items == null)) {
2.85 + this.items = n.items;
2.86 } else {
2.87 - this.items = new ArrayList<Pair>(n.items);
2.88 + this.items = new LinkedHashSet<Pair>(n.items);
2.89 }
2.90 }
2.91
3.1 --- a/openide.util/test/unit/src/org/openide/util/lookup/AbstractLookupBaseHid.java Thu Sep 13 07:59:50 2007 +0000
3.2 +++ b/openide.util/test/unit/src/org/openide/util/lookup/AbstractLookupBaseHid.java Thu Sep 13 16:19:36 2007 +0000
3.3 @@ -53,6 +53,9 @@
3.4
3.5 protected void setUp () {
3.6 this.ic = new InstanceContent ();
3.7 +
3.8 + beforeActualTest(getName());
3.9 +
3.10 this.instanceLookup = createInstancesLookup (ic);
3.11 this.lookup = createLookup (instanceLookup);
3.12 running = this;
3.13 @@ -1605,6 +1608,38 @@
3.14 assertGC("Result can disappear", ref2);
3.15 }
3.16
3.17 + void beforeActualTest(String n) {
3.18 + if (n.equals("testEqualsIsNotCalledTooMuch")) {
3.19 + CntPair.cnt = 0;
3.20 + CntPair.instances = 0;
3.21 + int how = 1000;
3.22 +
3.23 + for(int i = 0; i < how; i++) {
3.24 + this.ic.addPair(new CntPair("x" + i));
3.25 + }
3.26 +
3.27 + assertEquals("No equals called", 0, CntPair.cnt);
3.28 + assertEquals("1000 instances ", how, CntPair.instances);
3.29 + }
3.30 + }
3.31 +
3.32 + public void testEqualsIsNotCalledTooMuch() throws Exception {
3.33 + // most of the work done in beforeActualTest
3.34 +
3.35 + // desirable: assertEquals("no comparitions", 0, CntPair.cnt);
3.36 + // works for InheritanceTree, but not for ArrayStorage, but array
3.37 + // storages are generally small
3.38 +
3.39 + if (CntPair.cnt > 12000) {
3.40 + fail("Too much comparitions " + CntPair.cnt);
3.41 + }
3.42 + if (CntPair.hashCnt > 40000) {
3.43 + fail("Too much hashes: " + CntPair.hashCnt);
3.44 + }
3.45 +
3.46 + assertEquals("instaces is enough", 1000, CntPair.instances);
3.47 + }
3.48 +
3.49 /** Adds instances to the instance lookup.
3.50 */
3.51 private void addInstances (Object... instances) {
3.52 @@ -1711,6 +1746,66 @@
3.53 }
3.54 }
3.55 }
3.56 +
3.57 + private static final class CntPair extends AbstractLookup.Pair {
3.58 + private static int instances;
3.59 + private String txt;
3.60 +
3.61 + public CntPair(String txt) {
3.62 + this.txt = txt;
3.63 + instances++;
3.64 + }
3.65 +
3.66 + public static int hashCnt;
3.67 + @Override
3.68 + public int hashCode() {
3.69 + hashCnt++;
3.70 + return txt.hashCode() + 3777;
3.71 + }
3.72 +
3.73 + public static int cnt;
3.74 + @Override
3.75 + public boolean equals(Object obj) {
3.76 + cnt++;
3.77 +
3.78 + if (obj == null) {
3.79 + return false;
3.80 + }
3.81 + if (getClass() != obj.getClass()) {
3.82 + return false;
3.83 + }
3.84 + final CntPair other = (CntPair) obj;
3.85 + if (this.txt != other.txt && (this.txt == null || !this.txt.equals(other.txt))) {
3.86 + return false;
3.87 + }
3.88 + return true;
3.89 + }
3.90 +
3.91 + protected boolean instanceOf(Class c) {
3.92 + return c.isAssignableFrom(String.class);
3.93 + }
3.94 +
3.95 + protected boolean creatorOf(Object obj) {
3.96 + return obj == txt;
3.97 + }
3.98 +
3.99 + public Object getInstance() {
3.100 + return txt;
3.101 + }
3.102 +
3.103 + public Class getType() {
3.104 + return String.class;
3.105 + }
3.106 +
3.107 + public String getId() {
3.108 + return txt;
3.109 + }
3.110 +
3.111 + public String getDisplayName() {
3.112 + return txt;
3.113 + }
3.114 +
3.115 + }
3.116
3.117 public static final class SerialPair extends AbstractLookup.Pair
3.118 implements java.io.Serializable {