ObjectDirectory: avoid using File.getCanonicalPath()

On java 17 + Windows OS java.io.File.getCanonicalPath is a very slow
system call which uses most time during clone.

That is since JDK 12 the result of File.getCanonicalPath is not cached
anymore by default:
https://bugs.openjdk.java.net/browse/JDK-8207005

* Use toRealPath() to follow symbolic links also on windows.
* Cache the result.

Bug: 580568
Change-Id: I95f4f5b2babefd7210ee4740646230225ebf3788
This commit is contained in:
Jörg Kubitz 2022-08-15 11:05:04 +02:00 committed by Matthias Sohn
parent eb5124c74f
commit 2021ce3423
1 changed files with 15 additions and 7 deletions

View File

@ -724,14 +724,17 @@ public File fileFor(AnyObjectId objectId) {
static class AlternateHandle { static class AlternateHandle {
static class Id { static class Id {
String alternateId; private final String alternateId;
public Id(File object) { public Id(File object) {
String id = null;
try { try {
this.alternateId = object.getCanonicalPath(); // resolve symbolic links to their final target:
} catch (Exception e) { id = object.toPath().toRealPath().normalize().toString();
alternateId = null; } catch (Exception ignored) {
// id == null
} }
this.alternateId = id;
} }
@Override @Override
@ -757,6 +760,8 @@ public int hashCode() {
final ObjectDirectory db; final ObjectDirectory db;
private AlternateHandle.Id id;
AlternateHandle(ObjectDirectory db) { AlternateHandle(ObjectDirectory db) {
this.db = db; this.db = db;
} }
@ -765,8 +770,11 @@ void close() {
db.close(); db.close();
} }
public Id getId(){ public synchronized Id getId() {
return db.getAlternateId(); if (id == null) {
id = new AlternateHandle.Id(db.objects);
}
return id;
} }
} }
@ -795,6 +803,6 @@ CachedObjectDirectory newCachedFileObjectDatabase() {
} }
AlternateHandle.Id getAlternateId() { AlternateHandle.Id getAlternateId() {
return new AlternateHandle.Id(objects); return handle.getId();
} }
} }