mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 15:24:43 +02:00
8242959: Optimize ZipFile.getEntry by folding lookups for name and name+'/'
Reviewed-by: lancea, redestad
This commit is contained in:
parent
d185fe9953
commit
fc728278c2
1 changed files with 37 additions and 50 deletions
|
@ -1289,6 +1289,12 @@ public class ZipFile implements ZipConstants, Closeable {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final int hashN(byte[] a, int off, int len) {
|
private static final int hashN(byte[] a, int off, int len) {
|
||||||
|
// Performance optimization: getEntryPos assumes that the hash
|
||||||
|
// of a name remains unchanged when appending a trailing '/'.
|
||||||
|
if (len > 0 && a[off + len - 1] == '/') {
|
||||||
|
len--;
|
||||||
|
}
|
||||||
|
|
||||||
int h = 1;
|
int h = 1;
|
||||||
while (len-- > 0) {
|
while (len-- > 0) {
|
||||||
h = 31 * h + a[off++];
|
h = 31 * h + a[off++];
|
||||||
|
@ -1296,10 +1302,6 @@ public class ZipFile implements ZipConstants, Closeable {
|
||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final int hashAppend(int hash, byte b) {
|
|
||||||
return hash * 31 + b;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class End {
|
private static class End {
|
||||||
int centot; // 4 bytes
|
int centot; // 4 bytes
|
||||||
long cenlen; // 4 bytes
|
long cenlen; // 4 bytes
|
||||||
|
@ -1537,56 +1539,41 @@ public class ZipFile implements ZipConstants, Closeable {
|
||||||
}
|
}
|
||||||
int hsh = hashN(name, 0, name.length);
|
int hsh = hashN(name, 0, name.length);
|
||||||
int idx = table[(hsh & 0x7fffffff) % tablelen];
|
int idx = table[(hsh & 0x7fffffff) % tablelen];
|
||||||
boolean appendSlash = false;
|
|
||||||
/*
|
// Search down the target hash chain for a entry whose
|
||||||
* This while loop is an optimization where a double lookup
|
// 32 bit hash matches the hashed name.
|
||||||
* for name and name+/ is being performed. The name byte
|
while (idx != ZIP_ENDCHAIN) {
|
||||||
* array will be updated with an added slash only if the first
|
if (getEntryHash(idx) == hsh) {
|
||||||
* table lookup fails and there is a matching hash value for
|
// The CEN name must match the specfied one
|
||||||
* name+/.
|
int pos = getEntryPos(idx);
|
||||||
*/
|
final int nlen = CENNAM(cen, pos);
|
||||||
while (true) {
|
final int nstart = pos + CENHDR;
|
||||||
/*
|
|
||||||
* Search down the target hash chain for a entry whose
|
// If addSlash is true, we're testing for name+/ in
|
||||||
* 32 bit hash matches the hashed name.
|
// addition to name, unless name is the empty string
|
||||||
*/
|
// or already ends with a slash
|
||||||
while (idx != ZIP_ENDCHAIN) {
|
if (name.length == nlen ||
|
||||||
if (getEntryHash(idx) == hsh) {
|
(addSlash &&
|
||||||
if (appendSlash) {
|
name.length > 0 &&
|
||||||
name = Arrays.copyOf(name, name.length + 1);
|
name.length + 1 == nlen &&
|
||||||
name[name.length - 1] = '/';
|
cen[nstart + nlen - 1] == '/' &&
|
||||||
appendSlash = false;
|
name[name.length - 1] != '/')) {
|
||||||
|
boolean matched = true;
|
||||||
|
int nameoff = pos + CENHDR;
|
||||||
|
for (int i = 0; i < name.length; i++) {
|
||||||
|
if (name[i] != cen[nameoff++]) {
|
||||||
|
matched = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (matched) {
|
||||||
|
return pos;
|
||||||
}
|
}
|
||||||
// The CEN name must match the specfied one
|
|
||||||
int pos = getEntryPos(idx);
|
|
||||||
if (name.length == CENNAM(cen, pos)) {
|
|
||||||
boolean matched = true;
|
|
||||||
int nameoff = pos + CENHDR;
|
|
||||||
for (int i = 0; i < name.length; i++) {
|
|
||||||
if (name[i] != cen[nameoff++]) {
|
|
||||||
matched = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (matched) {
|
|
||||||
return pos;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
idx = getEntryNext(idx);
|
|
||||||
}
|
}
|
||||||
/* If not addSlash, or slash is already there, we are done */
|
idx = getEntryNext(idx);
|
||||||
if (!addSlash || name.length == 0 || name[name.length - 1] == '/') {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
// Add a slash to the hash code
|
|
||||||
hsh = hashAppend(hsh, (byte)'/');
|
|
||||||
// If we find a match on the new hash code, we need to append a
|
|
||||||
// slash when comparing
|
|
||||||
appendSlash = true;
|
|
||||||
idx = table[(hsh & 0x7fffffff) % tablelen];
|
|
||||||
addSlash = false;
|
|
||||||
}
|
}
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue