RefDirectory.scanRef: Re-use file existence check done in snapshot creation

Return immediately in scanRef if the loose ref was identified as
missing when a snapshot was attempted for the ref. This will help
performance of scanRef when the ref is packed but has a corresponding
empty dir in 'refs/'.

For example, consider the case where we create 50k sharded refs in
a new namespace called 'new-refs' using an atomic 'BatchRefUpdate'.
The refs are named like 'refs/new-refs/01/1/1', 'refs/new-refs/01/1/2',
'refs/new-refs/01/1/3' and so on. After the refs are created, the
'new-refs' namespace looks like below:

$ find refs/new-refs -type f | wc -l
0

$ find refs/new-refs -type d | wc -l
5101

At this point, an 'exactRef' call on each of the 50k refs without
this change takes ~2.5s, where as with this change it takes ~1.5s.

Change-Id: I926bc41b9ae89a1a792b1b5ec9a17b05271c906b
Signed-off-by: Kaushik Lingarkar <quic_kaushikl@quicinc.com>
This commit is contained in:
Kaushik Lingarkar 2021-11-29 12:14:56 -08:00 committed by Matthias Sohn
parent 5606a53151
commit f829f5f838
2 changed files with 13 additions and 0 deletions

View File

@ -439,6 +439,15 @@ public boolean equals(Object obj) {
return equals(other);
}
/**
* Check if the file exists
*
* @return true if the file exists
*/
public boolean fileExists() {
return !MISSING_FILEKEY.equals(this.fileKey);
}
/** {@inheritDoc} */
@Override
public int hashCode() {

View File

@ -1103,6 +1103,10 @@ LooseRef scanRef(LooseRef ref, String name) throws IOException {
final int limit = 4096;
final byte[] buf;
FileSnapshot otherSnapshot = FileSnapshot.save(path);
if (!otherSnapshot.fileExists()) {
return null;
}
try {
buf = IO.readSome(path, limit);
} catch (FileNotFoundException noFile) {