From 3cb59216f50f0af652dd0204654f820fed0e36fc Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Fri, 14 May 2010 14:03:32 -0700 Subject: [PATCH] Avoid unnecessary second read on OBJ_OFS_DELTA headers When we read the object header we copy 20 bytes from the pack data, then start parsing out the type and the inflated size. For most objects, this is only going to require 3 bytes, which is sufficient to represent objects with inflated sizes of up to 2^16. The local buffer however still has 17 bytes remaining in it, and that can be used to satisfy the OBJ_OFS_DELTA header. We shouldn't need to worry about walking off the end of the buffer here, because delta offsets cannot be larger than 64 bits, and that requires only 9 bytes in the OFS_DELTA encoding. Assuming worst-case scenarios of 9 bytes for the OFS_DELTA encoding, the pack file itself must be approaching 2^64 bytes, an infeasible size to store on any current technology. However, even if this were the case we still have 11 bytes for the type/size header. In that encoding we can represent an object as large as 2^74 bytes, which is also an infeasible size to process in JGit. So drop the second read here. The data offsets we pass into the ObjectLoaders being constructed need to be computed individually now. This saves a local variable, but pushes the addition operation into each branch of the switch. Change-Id: I6cf64697a9878db87bbf31c7636c03392b47a062 Signed-off-by: Shawn O. Pearce --- .../src/org/eclipse/jgit/lib/PackFile.java | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/PackFile.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/PackFile.java index bf6bc5924..b1d388667 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/PackFile.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/PackFile.java @@ -455,10 +455,9 @@ private void onOpenPack() throws IOException { private PackedObjectLoader reader(final WindowCursor curs, final long objOffset) throws IOException { - long pos = objOffset; int p = 0; final byte[] ib = curs.tempId; - readFully(pos, ib, 0, 20, curs); + readFully(objOffset, ib, 0, 20, curs); int c = ib[p++] & 0xff; final int typeCode = (c >> 4) & 7; long dataSize = c & 15; @@ -468,19 +467,16 @@ private PackedObjectLoader reader(final WindowCursor curs, dataSize += (c & 0x7f) << shift; shift += 7; } - pos += p; switch (typeCode) { case Constants.OBJ_COMMIT: case Constants.OBJ_TREE: case Constants.OBJ_BLOB: case Constants.OBJ_TAG: - return new WholePackedObjectLoader(this, pos, objOffset, typeCode, - (int) dataSize); + return new WholePackedObjectLoader(this, objOffset + p, objOffset, + typeCode, (int) dataSize); case Constants.OBJ_OFS_DELTA: { - readFully(pos, ib, 0, 20, curs); - p = 0; c = ib[p++] & 0xff; long ofs = c & 127; while ((c & 128) != 0) { @@ -489,12 +485,12 @@ private PackedObjectLoader reader(final WindowCursor curs, ofs <<= 7; ofs += (c & 127); } - return new DeltaOfsPackedObjectLoader(this, pos + p, objOffset, - (int) dataSize, objOffset - ofs); + return new DeltaOfsPackedObjectLoader(this, objOffset + p, + objOffset, (int) dataSize, objOffset - ofs); } case Constants.OBJ_REF_DELTA: { - readFully(pos, ib, 0, 20, curs); - return new DeltaRefPackedObjectLoader(this, pos + ib.length, + readFully(objOffset + p, ib, 0, 20, curs); + return new DeltaRefPackedObjectLoader(this, objOffset + p + 20, objOffset, (int) dataSize, ObjectId.fromRaw(ib)); } default: