]> source.dussan.org Git - jgit.git/commitdiff
DirCacheEntry: Speed up creation by avoiding string cast 16/61516/1
authorShawn Pearce <spearce@spearce.org>
Sat, 28 Nov 2015 16:58:15 +0000 (08:58 -0800)
committerShawn Pearce <spearce@spearce.org>
Sat, 28 Nov 2015 17:01:03 +0000 (09:01 -0800)
The checkPath function is available as a byte[] form, in fact the
String form just converts to byte[] to run the algorithm.

Having DirCacheEntry take a byte[] -> String -> byte[] to check if
each path is valid is a huge waste of CPU time. On some systems it
can double the time required to read 38,999 files from trees to the
DirCache. This slows down any operation using a DirCache.

Expose the byte[] form and use it for DirCacheEntry creation.

Change-Id: I6db7bc793ece99ff3c356338d793c07c061aeac7

org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheEntryTest.java
org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java
org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheEntry.java
org.eclipse.jgit/src/org/eclipse/jgit/util/SystemReader.java

index e159ed939e917677680f6bb820f3ad3c302e3cf8..dc7181aece7240eccd4c99f07093c14502d9ed9d 100644 (file)
@@ -69,9 +69,9 @@ public class DirCacheEntryTest {
                assertFalse(isValidPath("a\u0000b"));
        }
 
-       private static boolean isValidPath(final String path) {
+       private static boolean isValidPath(String path) {
                try {
-                       DirCacheCheckout.checkValidPath(path);
+                       new DirCacheEntry(path);
                        return true;
                } catch (InvalidPathException e) {
                        return false;
index 393a8549450df29db9ec1bc72fead5118d3351c7..4eb688170c3f58ef745b6116e4bba95f9f817266 100644 (file)
@@ -1342,24 +1342,6 @@ public class DirCacheCheckout {
                        checkValidPathSegment(chk, i);
        }
 
-       /**
-        * Check if path is a valid path for a checked out file name or ref name.
-        *
-        * @param path
-        * @throws InvalidPathException
-        *             if the path is invalid
-        * @since 3.3
-        */
-       static void checkValidPath(String path) throws InvalidPathException {
-               try {
-                       SystemReader.getInstance().checkPath(path);
-               } catch (CorruptObjectException e) {
-                       InvalidPathException p = new InvalidPathException(path);
-                       p.initCause(e);
-                       throw p;
-               }
-       }
-
        private static void checkValidPathSegment(ObjectChecker chk,
                        CanonicalTreeParser t) throws InvalidPathException {
                try {
index eef2e6d3c34a64d5ee705a7eee583a4311fadd09..404ff1738e3d55471715ffec624ec26d1cb22065 100644 (file)
@@ -65,6 +65,7 @@ import org.eclipse.jgit.lib.ObjectId;
 import org.eclipse.jgit.util.IO;
 import org.eclipse.jgit.util.MutableInteger;
 import org.eclipse.jgit.util.NB;
+import org.eclipse.jgit.util.SystemReader;
 
 /**
  * A single file (or stage of a file) in a {@link DirCache}.
@@ -191,7 +192,7 @@ public class DirCacheEntry {
                }
 
                try {
-                       DirCacheCheckout.checkValidPath(toString(path));
+                       checkPath(path);
                } catch (InvalidPathException e) {
                        CorruptObjectException p =
                                new CorruptObjectException(e.getMessage());
@@ -263,7 +264,7 @@ public class DirCacheEntry {
        /**
         * Create an empty entry at the specified stage.
         *
-        * @param newPath
+        * @param path
         *            name of the cache entry, in the standard encoding.
         * @param stage
         *            the stage index of the new entry.
@@ -274,16 +275,16 @@ public class DirCacheEntry {
         *             range 0..3, inclusive.
         */
        @SuppressWarnings("boxing")
-       public DirCacheEntry(final byte[] newPath, final int stage) {
-               DirCacheCheckout.checkValidPath(toString(newPath));
+       public DirCacheEntry(byte[] path, final int stage) {
+               checkPath(path);
                if (stage < 0 || 3 < stage)
                        throw new IllegalArgumentException(MessageFormat.format(
                                        JGitText.get().invalidStageForPath,
-                                       stage, toString(newPath)));
+                                       stage, toString(path)));
 
                info = new byte[INFO_LEN];
                infoOffset = 0;
-               path = newPath;
+               this.path = path;
 
                int flags = ((stage & 0x3) << 12);
                if (path.length < NAME_MASK)
@@ -730,6 +731,16 @@ public class DirCacheEntry {
                        return 0;
        }
 
+       private static void checkPath(byte[] path) {
+               try {
+                       SystemReader.getInstance().checkPath(path);
+               } catch (CorruptObjectException e) {
+                       InvalidPathException p = new InvalidPathException(toString(path));
+                       p.initCause(e);
+                       throw p;
+               }
+       }
+
        private static String toString(final byte[] path) {
                return Constants.CHARSET.decode(ByteBuffer.wrap(path)).toString();
        }
index 4795c89e73388e6279b85bb57684672359b53034..9860ef070f7d7ffe43fee929daba04fd16147d26 100644 (file)
@@ -339,4 +339,19 @@ public abstract class SystemReader {
        public void checkPath(String path) throws CorruptObjectException {
                platformChecker.checkPath(path);
        }
+
+       /**
+        * Check tree path entry for validity.
+        * <p>
+        * Scans a multi-directory path string such as {@code "src/main.c"}.
+        *
+        * @param path
+        *            path string to scan.
+        * @throws CorruptObjectException
+        *             path is invalid.
+        * @since 4.2
+        */
+       public void checkPath(byte[] path) throws CorruptObjectException {
+               platformChecker.checkPath(path, 0, path.length);
+       }
 }