< prev index next >

src/java.base/unix/classes/java/io/UnixFileSystem.java

Print this page
rev 59556 : 8246338: Reduce overhead of normalizing file paths
Reviewed-by: TBD

@@ -62,18 +62,21 @@
     }
 
     /* A normal Unix pathname contains no duplicate slashes and does not end
        with a slash.  It may be the empty string. */
 
-    /* Normalize the given pathname, whose length is len, starting at the given
-       offset; everything before this offset is already normal. */
-    private String normalize(String pathname, int len, int off) {
-        if (len == 0) return pathname;
-        int n = len;
+    /**
+     * Normalize the given pathname, starting at the given
+     * offset; everything before off is already normal, and there's at least
+     * one duplicate or trailing slash to be removed
+     */
+    private String normalize(String pathname, int off) {
+        int n = pathname.length();
         while ((n > 0) && (pathname.charAt(n - 1) == '/')) n--;
         if (n == 0) return "/";
-        StringBuilder sb = new StringBuilder(pathname.length());
+
+        StringBuilder sb = new StringBuilder(n);
         if (off > 0) sb.append(pathname, 0, off);
         char prevChar = 0;
         for (int i = off; i < n; i++) {
             char c = pathname.charAt(i);
             if ((prevChar == '/') && (c == '/')) continue;

@@ -86,26 +89,23 @@
     /* Check that the given pathname is normal.  If not, invoke the real
        normalizer on the part of the pathname that requires normalization.
        This way we iterate through the whole pathname string only once. */
     @Override
     public String normalize(String pathname) {
-        int n = pathname.length();
-        char prevChar = 0;
-        for (int i = 0; i < n; i++) {
-            char c = pathname.charAt(i);
-            if ((prevChar == '/') && (c == '/'))
-                return normalize(pathname, n, i - 1);
-            prevChar = c;
+        int doubleSlash = pathname.indexOf("//");
+        if (doubleSlash >= 0) {
+            return normalize(pathname, doubleSlash);
+        }
+        if (pathname.endsWith("/")) {
+            return normalize(pathname, pathname.length() - 1);
         }
-        if (prevChar == '/') return normalize(pathname, n, n - 1);
         return pathname;
     }
 
     @Override
     public int prefixLength(String pathname) {
-        if (pathname.isEmpty()) return 0;
-        return (pathname.charAt(0) == '/') ? 1 : 0;
+        return pathname.startsWith("/") ? 1 : 0;
     }
 
     @Override
     public String resolve(String parent, String child) {
         if (child.isEmpty()) return parent;
< prev index next >