Browse Source

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 <spearce@spearce.org>
stable-0.8
Shawn O. Pearce 15 years ago
parent
commit
3cb59216f5
  1. 18
      org.eclipse.jgit/src/org/eclipse/jgit/lib/PackFile.java

18
org.eclipse.jgit/src/org/eclipse/jgit/lib/PackFile.java

@ -455,10 +455,9 @@ public class PackFile implements Iterable<PackIndex.MutableEntry> {
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 @@ public class PackFile implements Iterable<PackIndex.MutableEntry> {
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 @@ public class PackFile implements Iterable<PackIndex.MutableEntry> {
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:

Loading…
Cancel
Save