Browse Source

DirCacheEntry: Speed up creation by avoiding string cast

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
stable-4.3
Shawn Pearce 9 years ago
parent
commit
761814fe9c
  1. 4
      org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheEntryTest.java
  2. 18
      org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java
  3. 23
      org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheEntry.java
  4. 15
      org.eclipse.jgit/src/org/eclipse/jgit/util/SystemReader.java

4
org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheEntryTest.java vendored

@ -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;

18
org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java vendored

@ -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 {

23
org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheEntry.java vendored

@ -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();
}

15
org.eclipse.jgit/src/org/eclipse/jgit/util/SystemReader.java

@ -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);
}
}

Loading…
Cancel
Save