Browse Source

SHA1: support reset() and reuse instances

Allow SHA1 instances to be reused to compute another hash value, and
resume caching them in ObjectInserter and PackParser.  This shaves a
small amount of running time off parsing git.git's pack file:

  before   after
  ------   ------
  25.25s   25.55s
  25.48s   25.06s
  25.26s   24.94s

Almost noise (small difference), but recycling the instances reduces
some stress on the memory allocator finding two 80 word message block
arrays needed for hashing and collision detection.

Change-Id: I4af88a720e81460293bc5c5d1d3db1a831e7e228
tags/v4.7.0.201704051617-r
Shawn Pearce 7 years ago
parent
commit
1bf7d3f290

+ 15
- 0
org.eclipse.jgit.test/tst/org/eclipse/jgit/util/sha1/SHA1Test.java View File

s.update(new byte[] {}); s.update(new byte[] {});
ObjectId s1 = ObjectId.fromRaw(s.digest()); ObjectId s1 = ObjectId.fromRaw(s.digest());


s.reset();
s.update(new byte[] {});
ObjectId s2 = s.toObjectId();

assertEquals(m1, s1); assertEquals(m1, s1);
assertEquals(exp, s1); assertEquals(exp, s1);
assertEquals(exp, s2);
} }


@Test @Test
s.update(TEST1.getBytes(StandardCharsets.UTF_8)); s.update(TEST1.getBytes(StandardCharsets.UTF_8));
ObjectId s1 = ObjectId.fromRaw(s.digest()); ObjectId s1 = ObjectId.fromRaw(s.digest());


s.reset();
s.update(TEST1.getBytes(StandardCharsets.UTF_8));
ObjectId s2 = s.toObjectId();

assertEquals(m1, s1); assertEquals(m1, s1);
assertEquals(exp, s1); assertEquals(exp, s1);
assertEquals(exp, s2);
} }


@Test @Test
s.update(TEST2.getBytes(StandardCharsets.UTF_8)); s.update(TEST2.getBytes(StandardCharsets.UTF_8));
ObjectId s1 = ObjectId.fromRaw(s.digest()); ObjectId s1 = ObjectId.fromRaw(s.digest());


s.reset();
s.update(TEST2.getBytes(StandardCharsets.UTF_8));
ObjectId s2 = s.toObjectId();

assertEquals(m1, s1); assertEquals(m1, s1);
assertEquals(exp, s1); assertEquals(exp, s1);
assertEquals(exp, s2);
} }
} }

+ 1
- 1
org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsInserter.java View File

} }


long offset = beginObject(type, len); long offset = beginObject(type, len);
SHA1 md = SHA1.newInstance();
SHA1 md = digest();
md.update(Constants.encodedTypeString(type)); md.update(Constants.encodedTypeString(type));
md.update((byte) ' '); md.update((byte) ' ');
md.update(Constants.encodeASCII(len)); md.update(Constants.encodeASCII(len));

+ 1
- 1
org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/ObjectDirectoryInserter.java View File

return insert(type, buf, 0, actLen, createDuplicate); return insert(type, buf, 0, actLen, createDuplicate);


} else { } else {
SHA1 md = SHA1.newInstance();
SHA1 md = digest();
File tmp = toTemp(md, type, len, is); File tmp = toTemp(md, type, len, is);
ObjectId id = md.toObjectId(); ObjectId id = md.toObjectId();
return insertOneObject(tmp, id, createDuplicate); return insertOneObject(tmp, id, createDuplicate);

+ 3
- 1
org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectInserter.java View File

} }
} }


private final SHA1 hasher = SHA1.newInstance();

/** Temporary working buffer for streaming data through. */ /** Temporary working buffer for streaming data through. */
private byte[] tempBuffer; private byte[] tempBuffer;




/** @return digest to help compute an ObjectId */ /** @return digest to help compute an ObjectId */
protected SHA1 digest() { protected SHA1 digest() {
return SHA1.newInstance();
return hasher.reset();
} }


/** /**

+ 3
- 2
org.eclipse.jgit/src/org/eclipse/jgit/transport/PackParser.java View File



private byte[] hdrBuf; private byte[] hdrBuf;


private final SHA1 objectHasher = SHA1.newInstance();
private final MutableObjectId tempObjectId; private final MutableObjectId tempObjectId;


private InputStream in; private InputStream in;
JGitText.get().corruptionDetectedReReadingAt, JGitText.get().corruptionDetectedReReadingAt,
Long.valueOf(visit.delta.position))); Long.valueOf(visit.delta.position)));


SHA1 objectDigest = SHA1.newInstance();
SHA1 objectDigest = objectHasher.reset();
objectDigest.update(Constants.encodedTypeString(type)); objectDigest.update(Constants.encodedTypeString(type));
objectDigest.update((byte) ' '); objectDigest.update((byte) ' ');
objectDigest.update(Constants.encodeASCII(visit.data.length)); objectDigest.update(Constants.encodeASCII(visit.data.length));


private void whole(final long pos, final int type, final long sz) private void whole(final long pos, final int type, final long sz)
throws IOException { throws IOException {
SHA1 objectDigest = SHA1.newInstance();
SHA1 objectDigest = objectHasher.reset();
objectDigest.update(Constants.encodedTypeString(type)); objectDigest.update(Constants.encodedTypeString(type));
objectDigest.update((byte) ' '); objectDigest.update((byte) ' ');
objectDigest.update(Constants.encodeASCII(sz)); objectDigest.update(Constants.encodeASCII(sz));

+ 26
- 6
org.eclipse.jgit/src/org/eclipse/jgit/util/sha1/SHA1.java View File

return new SHA1(); return new SHA1();
} }


// Magic initialization constants defined by FIPS180.
private int h0 = 0x67452301;
private int h1 = 0xEFCDAB89;
private int h2 = 0x98BADCFE;
private int h3 = 0x10325476;
private int h4 = 0xC3D2E1F0;
private int h0;
private int h1;
private int h2;
private int h3;
private int h4;
private final int[] w = new int[80]; private final int[] w = new int[80];


/** Buffer to accumulate partial blocks to 64 byte alignment. */ /** Buffer to accumulate partial blocks to 64 byte alignment. */
private long length; private long length;


private SHA1() { private SHA1() {
init();
}

/**
* Reset this instance to compute another hash.
*
* @return {@code this}.
*/
public SHA1 reset() {
init();
length = 0;
return this;
}

private void init() {
// Magic initialization constants defined by FIPS180.
h0 = 0x67452301;
h1 = 0xEFCDAB89;
h2 = 0x98BADCFE;
h3 = 0x10325476;
h4 = 0xC3D2E1F0;
} }


/** /**

Loading…
Cancel
Save