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
This commit is contained in:
parent
0f25f64d48
commit
1bf7d3f290
|
@ -72,8 +72,13 @@ public void test0() throws NoSuchAlgorithmException {
|
|||
s.update(new byte[] {});
|
||||
ObjectId s1 = ObjectId.fromRaw(s.digest());
|
||||
|
||||
s.reset();
|
||||
s.update(new byte[] {});
|
||||
ObjectId s2 = s.toObjectId();
|
||||
|
||||
assertEquals(m1, s1);
|
||||
assertEquals(exp, s1);
|
||||
assertEquals(exp, s2);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -89,8 +94,13 @@ public void test1() throws NoSuchAlgorithmException {
|
|||
s.update(TEST1.getBytes(StandardCharsets.UTF_8));
|
||||
ObjectId s1 = ObjectId.fromRaw(s.digest());
|
||||
|
||||
s.reset();
|
||||
s.update(TEST1.getBytes(StandardCharsets.UTF_8));
|
||||
ObjectId s2 = s.toObjectId();
|
||||
|
||||
assertEquals(m1, s1);
|
||||
assertEquals(exp, s1);
|
||||
assertEquals(exp, s2);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -106,7 +116,12 @@ public void test2() throws NoSuchAlgorithmException {
|
|||
s.update(TEST2.getBytes(StandardCharsets.UTF_8));
|
||||
ObjectId s1 = ObjectId.fromRaw(s.digest());
|
||||
|
||||
s.reset();
|
||||
s.update(TEST2.getBytes(StandardCharsets.UTF_8));
|
||||
ObjectId s2 = s.toObjectId();
|
||||
|
||||
assertEquals(m1, s1);
|
||||
assertEquals(exp, s1);
|
||||
assertEquals(exp, s2);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -169,7 +169,7 @@ public ObjectId insert(int type, long len, InputStream in)
|
|||
}
|
||||
|
||||
long offset = beginObject(type, len);
|
||||
SHA1 md = SHA1.newInstance();
|
||||
SHA1 md = digest();
|
||||
md.update(Constants.encodedTypeString(type));
|
||||
md.update((byte) ' ');
|
||||
md.update(Constants.encodeASCII(len));
|
||||
|
|
|
@ -140,7 +140,7 @@ ObjectId insert(int type, long len, InputStream is, boolean createDuplicate)
|
|||
return insert(type, buf, 0, actLen, createDuplicate);
|
||||
|
||||
} else {
|
||||
SHA1 md = SHA1.newInstance();
|
||||
SHA1 md = digest();
|
||||
File tmp = toTemp(md, type, len, is);
|
||||
ObjectId id = md.toObjectId();
|
||||
return insertOneObject(tmp, id, createDuplicate);
|
||||
|
|
|
@ -177,6 +177,8 @@ public void close() {
|
|||
}
|
||||
}
|
||||
|
||||
private final SHA1 hasher = SHA1.newInstance();
|
||||
|
||||
/** Temporary working buffer for streaming data through. */
|
||||
private byte[] tempBuffer;
|
||||
|
||||
|
@ -217,7 +219,7 @@ protected byte[] buffer() {
|
|||
|
||||
/** @return digest to help compute an ObjectId */
|
||||
protected SHA1 digest() {
|
||||
return SHA1.newInstance();
|
||||
return hasher.reset();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -117,6 +117,7 @@ public static enum Source {
|
|||
|
||||
private byte[] hdrBuf;
|
||||
|
||||
private final SHA1 objectHasher = SHA1.newInstance();
|
||||
private final MutableObjectId tempObjectId;
|
||||
|
||||
private InputStream in;
|
||||
|
@ -665,7 +666,7 @@ private void resolveDeltas(DeltaVisit visit, final int type,
|
|||
JGitText.get().corruptionDetectedReReadingAt,
|
||||
Long.valueOf(visit.delta.position)));
|
||||
|
||||
SHA1 objectDigest = SHA1.newInstance();
|
||||
SHA1 objectDigest = objectHasher.reset();
|
||||
objectDigest.update(Constants.encodedTypeString(type));
|
||||
objectDigest.update((byte) ' ');
|
||||
objectDigest.update(Constants.encodeASCII(visit.data.length));
|
||||
|
@ -1023,7 +1024,7 @@ private void indexOneObject() throws IOException {
|
|||
|
||||
private void whole(final long pos, final int type, final long sz)
|
||||
throws IOException {
|
||||
SHA1 objectDigest = SHA1.newInstance();
|
||||
SHA1 objectDigest = objectHasher.reset();
|
||||
objectDigest.update(Constants.encodedTypeString(type));
|
||||
objectDigest.update((byte) ' ');
|
||||
objectDigest.update(Constants.encodeASCII(sz));
|
||||
|
|
|
@ -63,12 +63,11 @@ public static SHA1 newInstance() {
|
|||
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];
|
||||
|
||||
/** Buffer to accumulate partial blocks to 64 byte alignment. */
|
||||
|
@ -78,6 +77,27 @@ public static SHA1 newInstance() {
|
|||
private long length;
|
||||
|
||||
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…
Reference in New Issue