[infinispan-commits] Infinispan SVN: r738 - in trunk/tree/src: test/java/org/infinispan/profiling/testinternals and 1 other directory.
infinispan-commits at lists.jboss.org
infinispan-commits at lists.jboss.org
Wed Aug 26 08:44:21 EDT 2009
Author: manik.surtani at jboss.com
Date: 2009-08-26 08:44:21 -0400 (Wed, 26 Aug 2009)
New Revision: 738
Modified:
trunk/tree/src/main/java/org/infinispan/tree/Fqn.java
trunk/tree/src/test/java/org/infinispan/profiling/testinternals/FqnGenerator.java
Log:
[ISPN-169] (Improve the performance of Fqns by backing with an immutable array rather than a list)
Modified: trunk/tree/src/main/java/org/infinispan/tree/Fqn.java
===================================================================
--- trunk/tree/src/main/java/org/infinispan/tree/Fqn.java 2009-08-26 10:52:42 UTC (rev 737)
+++ trunk/tree/src/main/java/org/infinispan/tree/Fqn.java 2009-08-26 12:44:21 UTC (rev 738)
@@ -23,17 +23,14 @@
import net.jcip.annotations.Immutable;
-
import org.infinispan.marshall.Ids;
import org.infinispan.marshall.Marshallable;
-import org.infinispan.util.Immutables;
+import org.infinispan.util.Util;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
-import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collections;
import java.util.List;
/**
@@ -89,9 +86,8 @@
*/
public static final String SEPARATOR = "/";
- protected List<Object> elements;
+ private final Object[] elements;
private transient int hash_code = 0;
- protected int size = 0;
/**
* Immutable root Fqn.
@@ -109,33 +105,31 @@
* Public to satisfy Externalization. // TODO: Remove this ctor as well as Externalization!!
*/
public Fqn() {
- elements = Collections.emptyList();
- size = 0;
+ elements = new Object[]{};
}
+ private Fqn(Object... elements) {
+ this.elements = elements;
+ }
+
/**
* If safe is false, Collections.unmodifiableList() is used to wrap the list passed in. This is an optimisation so
* Fqn.fromString(), probably the most frequently used factory method, doesn't end up needing to use the
* unmodifiableList() since it creates the list internally.
*
* @param names List of names
- * @param safe whether this list is referenced externally (safe = false) or not (safe = true).
*/
- @SuppressWarnings("unchecked")
- private Fqn(List names, boolean safe) {
- if (names != null) {
- // if not safe make a defensive copy
- elements = safe ? names : Immutables.immutableListCopy(names);
- size = elements.size();
- } else {
- elements = Collections.emptyList();
- size = 0;
- }
+ private Fqn(List names) {
+ if (names != null)
+ elements = names.toArray();
+ else
+ elements = new Object[]{};
}
- private Fqn(Fqn base, List relative) {
- elements = Immutables.immutableListMerge(base.elements, relative);
- size = elements.size();
+ private Fqn(Fqn base, Object... relative) {
+ elements = new Object[base.elements.length + relative.length];
+ System.arraycopy(base.elements, 0, elements, 0, base.elements.length);
+ System.arraycopy(relative, 0, elements, base.elements.length, relative.length);
}
// ----------------- END: Private constructors for use by factory methods only. ----------------------
@@ -149,26 +143,10 @@
*/
@SuppressWarnings("unchecked")
public static Fqn fromList(List names) {
- return new Fqn(names, false);
+ return new Fqn(names);
}
/**
- * Retrieves an Fqn that represents the list of elements passed in.
- *
- * @param names list of elements that comprise the Fqn
- * @param safe if true, the list passed in is not defensively copied but used directly. <b>Use with care.</b> Make
- * sure you know what you are doing before you pass in a <tt>true</tt> value to <tt>safe</tt>, as it can
- * have adverse effects on performance or correctness. The defensive copy of list elements is not just
- * for safety but also for performance as an appropriare List implementation is used, which works well
- * with Fqn operations.
- * @return an Fqn
- */
- @SuppressWarnings("unchecked")
- public static Fqn fromList(List names, boolean safe) {
- return new Fqn(names, safe);
- }
-
- /**
* Retrieves an Fqn that represents the array of elements passed in.
*
* @param elements array of elements that comprise the Fqn
@@ -176,7 +154,9 @@
* @since 4.0
*/
public static Fqn fromElements(Object... elements) {
- return new Fqn(Arrays.asList(elements), true);
+ Object[] copy = new Object[elements.length];
+ System.arraycopy(elements, 0, copy, 0, elements.length);
+ return new Fqn(copy);
}
/**
@@ -200,7 +180,7 @@
* @since 4.0
*/
public static Fqn fromRelativeList(Fqn base, List relativeElements) {
- return new Fqn(base, relativeElements);
+ return new Fqn(base, relativeElements.toArray());
}
/**
@@ -212,7 +192,7 @@
* @since 4.0
*/
public static Fqn fromRelativeElements(Fqn base, Object... relativeElements) {
- return new Fqn(base, Arrays.asList(relativeElements));
+ return new Fqn(base, relativeElements);
}
/**
@@ -236,7 +216,7 @@
String toMatch = stringRepresentation.startsWith(SEPARATOR) ? stringRepresentation.substring(1) : stringRepresentation;
Object[] el = toMatch.split(SEPARATOR);
- return new Fqn(Immutables.immutableListWrap(el), true);
+ return new Fqn(el);
}
/**
@@ -261,15 +241,18 @@
* @return a subFqn
*/
public Fqn getSubFqn(int startIndex, int endIndex) {
- List el = elements.subList(startIndex, endIndex);
- return new Fqn(el, true);
+ if (endIndex < startIndex) throw new IllegalArgumentException("End index cannot be less than the start index!");
+ int len = endIndex - startIndex;
+ Object[] el = new Object[len];
+ System.arraycopy(elements, startIndex, el, 0, len);
+ return new Fqn(el);
}
/**
* @return the number of elements in the Fqn. The root node contains zero.
*/
public int size() {
- return size;
+ return elements.length;
}
/**
@@ -277,7 +260,7 @@
* @return Returns the nth element in the Fqn.
*/
public Object get(int n) {
- return elements.get(n);
+ return elements[n];
}
/**
@@ -286,7 +269,7 @@
*/
public Object getLastElement() {
if (isRoot()) return null;
- return elements.get(size - 1);
+ return elements[elements.length - 1];
}
/**
@@ -294,9 +277,22 @@
* @return true if the Fqn contains this element, false otherwise.
*/
public boolean hasElement(Object element) {
- return elements.indexOf(element) != -1;
+ return indexOf(element) != -1;
}
+ private int indexOf(Object element) {
+ if (element == null) {
+ for (int i = 0; i < elements.length; i++) {
+ if (elements[i] == null) return i;
+ }
+ } else {
+ for (int i = 0; i < elements.length; i++) {
+ if (element.equals(elements[i])) return i;
+ }
+ }
+ return -1;
+ }
+
/**
* Returns true if obj is a Fqn with the same elements.
*/
@@ -309,7 +305,11 @@
return false;
}
Fqn other = (Fqn) obj;
- return size == other.size() && elements.equals(other.elements);
+ if (elements.length != other.elements.length) return false;
+ for (int i = elements.length - 1; i >= 0; i--) {
+ if (!Util.safeEquals(elements[i], other.elements[i])) return false;
+ }
+ return true;
}
/**
@@ -353,7 +353,7 @@
* @return true if the target is a child of parentFqn
*/
public boolean isChildOf(Fqn parentFqn) {
- return parentFqn.size() != size && isChildOrEquals(parentFqn);
+ return parentFqn.elements.length != elements.length && isChildOrEquals(parentFqn);
}
@@ -364,7 +364,7 @@
* @return true if this is a direct child, false otherwise.
*/
public boolean isDirectChildOf(Fqn parentFqn) {
- return size == parentFqn.size() + 1 && isChildOf(parentFqn);
+ return elements.length == parentFqn.elements.length + 1 && isChildOf(parentFqn);
}
/**
@@ -381,14 +381,12 @@
* @return true if this Fqn is equals or the child of parentFqn.
*/
public boolean isChildOrEquals(Fqn parentFqn) {
- List parentList = parentFqn.elements;
- if (parentList.size() > size) {
+ Object[] parentEl = parentFqn.elements;
+ if (parentEl.length > elements.length) {
return false;
}
- for (int i = parentList.size() - 1; i >= 0; i--) {
- if (!parentList.get(i).equals(elements.get(i))) {
- return false;
- }
+ for (int i = parentEl.length - 1; i >= 0; i--) {
+ if (!Util.safeEquals(parentEl[i], elements[i])) return false;
}
return true;
}
@@ -405,7 +403,7 @@
return hashCode;
}
- protected String getStringRepresentation(List elements) {
+ protected String getStringRepresentation(Object[] elements) {
StringBuilder builder = new StringBuilder();
for (Object e : elements) {
// incase user element 'e' does not implement equals() properly, don't rely on their implementation.
@@ -431,12 +429,12 @@
* @return the parent Fqn
*/
public Fqn getParent() {
- switch (size) {
+ switch (elements.length) {
case 0:
case 1:
return root();
default:
- return new Fqn(elements.subList(0, size - 1), true);
+ return getSubFqn(0, elements.length - 1);
}
}
@@ -451,7 +449,7 @@
* @return true if the Fqn is Fqn.ROOT.
*/
public boolean isRoot() {
- return size == 0;
+ return elements.length == 0;
}
/**
@@ -478,7 +476,7 @@
* @return an unmodifiable list
*/
public List peekElements() {
- return elements;
+ return Arrays.asList(elements);
}
/**
@@ -501,19 +499,19 @@
Fqn subFqn = this.getSubFqn(oldAncestor.size(), size());
return Fqn.fromRelativeFqn(newAncestor, subFqn);
}
-
+
public static class Externalizer implements org.infinispan.marshall.Externalizer {
public void writeObject(ObjectOutput output, Object object) throws IOException {
Fqn fqn = (Fqn) object;
- output.writeShort(fqn.size);
+ output.writeInt(fqn.elements.length);
for (Object element : fqn.elements) output.writeObject(element);
}
public Object readObject(ObjectInput input) throws IOException, ClassNotFoundException {
- short size = input.readShort();
- List elements = new ArrayList(size);
- for (int i = 0; i < size; i++) elements.add(input.readObject());
- return Fqn.fromList(elements);
+ int size = input.readInt();
+ Object[] elements = new Object[size];
+ for (int i = 0; i < size; i++) elements[i] = input.readObject();
+ return new Fqn(elements);
}
}
}
\ No newline at end of file
Modified: trunk/tree/src/test/java/org/infinispan/profiling/testinternals/FqnGenerator.java
===================================================================
--- trunk/tree/src/test/java/org/infinispan/profiling/testinternals/FqnGenerator.java 2009-08-26 10:52:42 UTC (rev 737)
+++ trunk/tree/src/test/java/org/infinispan/profiling/testinternals/FqnGenerator.java 2009-08-26 12:44:21 UTC (rev 738)
@@ -15,12 +15,12 @@
public class FqnGenerator {
- private static final Random r = new Random();
+ private static final Random r = new Random();
public static Fqn createRandomFqn(int depth) {
List<String> fqnElements = new ArrayList<String>(depth);
for (int i = 0; i < depth; i++) fqnElements.add(Integer.toHexString(r.nextInt(Integer.MAX_VALUE)));
- return Fqn.fromList(fqnElements, true);
+ return Fqn.fromList(fqnElements);
}
More information about the infinispan-commits
mailing list