Bug 570896: Optimize comparePathUri for normal URIs

If URI is already normal u.normalize() will just return u.
i.e. no memory allocation.

Change-Id: I379d3b3460b3444f1a99b938c5f4c6ee433d69ea
Signed-off-by: Joerg Kubitz <jkubitz-eclipse@gmx.de>
diff --git a/bundles/org.eclipse.core.filesystem/src/org/eclipse/core/internal/filesystem/FileStoreUtil.java b/bundles/org.eclipse.core.filesystem/src/org/eclipse/core/internal/filesystem/FileStoreUtil.java
index cb1881c..ae3c31f 100644
--- a/bundles/org.eclipse.core.filesystem/src/org/eclipse/core/internal/filesystem/FileStoreUtil.java
+++ b/bundles/org.eclipse.core.filesystem/src/org/eclipse/core/internal/filesystem/FileStoreUtil.java
@@ -15,8 +15,6 @@
 
 import java.net.URI;
 import org.eclipse.core.filesystem.IFileStore;
-import org.eclipse.core.runtime.IPath;
-import org.eclipse.core.runtime.Path;
 
 /**
  * Provides internal utility functions for comparing FileStores and paths
@@ -28,8 +26,9 @@
 	}
 
 	/**
-	 * Compares URIs by normalized IPath
-	 * This is the old slow implementation and has a memory hotspot see bug 570896. Prefer to use compareNormalisedUri!
+	 * Compares URIs by their normalized values.
+	 * This implementation has a memory hotspot when uri is not normalized.
+	 * see bug 570896!
 	 * @since org.eclipse.core.filesystem 1.9
 	 */
 	private static int comparePathUri(URI uri1, URI uri2) {
@@ -40,40 +39,22 @@
 		// in case of Exceptions:
 		if ((compare = nullsLast(uri1, uri2)) != 0)
 			return compare;
-		// compare hosts
-		compare = compareStringOrNull(uri1.getHost(), uri2.getHost());
-		if (compare != 0)
-			return compare;
-		// compare user infos
-		compare = compareStringOrNull(uri1.getUserInfo(), uri2.getUserInfo());
-		if (compare != 0)
-			return compare;
-		// compare ports
-		int port1 = uri1.getPort();
-		int port2 = uri2.getPort();
-		if (port1 != port2)
-			return port1 - port2;
+		// note: If uri is already normal u.normalize() will just return u:
+		return compareNormalisedUri(uri1.normalize(), uri2.normalize());
+	}
 
-		IPath path1 = new Path(uri1.getPath());
-		IPath path2 = new Path(uri2.getPath());
-		// compare devices
-		compare = compareStringOrNull(path1.getDevice(), path2.getDevice());
-		if (compare != 0)
-			return compare;
-		// compare segments
-		int segmentCount1 = path1.segmentCount();
-		int segmentCount2 = path2.segmentCount();
-		for (int i = 0; (i < segmentCount1) && (i < segmentCount2); i++) {
-			compare = path1.segment(i).compareTo(path2.segment(i));
-			if (compare != 0)
-				return compare;
-		}
-		//all segments are equal, so compare based on number of segments
-		compare = segmentCount1 - segmentCount2;
-		if (compare != 0)
-			return compare;
-		//same number of segments, so compare query
-		return compareStringOrNull(uri1.getQuery(), uri2.getQuery());
+	private static int compareNormalisedUri(URI uri1, URI uri2) {
+		int c;
+		// avoid to use IPath here due to high ephemeral memory allocation (Bug 570896)
+		if ((c = compareStringOrNull(uri1.getAuthority(), uri2.getAuthority())) != 0)
+			return c;
+		if ((c = compareStringOrNull(uri1.getScheme(), uri2.getScheme())) != 0)
+			return c;
+		if ((c = comparePathSegments(uri1.getPath(), uri2.getPath())) != 0)
+			return c;
+		if ((c = compareStringOrNull(uri1.getQuery(), uri2.getQuery())) != 0)
+			return c;
+		return c;
 	}
 
 	static int nullsLast(Object c1, Object c2) {