mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-22 06:02:11 +02:00
Bug 565553 - Improve performance of build command parsers with large number of files
Add more caches for methods in AbstractLanguageSettingsOutputScanner that are IO heavy: - getFilesystemLocation - determineMappedURI - resolvePathEntryInFilesystem (File.exists) These cut down the execution time of command parsing by around 50% on Windows, more so when considering Java >=12 when File.getCanonicalPath/File caching is not manually enabled. See also https://bugs.eclipse.org/bugs/show_bug.cgi?id=565553#c17 and https://bugs.java.com/bugdatabase/view_bug.do?bug_id=8258036 Change-Id: I80828f969547f824d2e45e60b5f4459d03c70bb1 Signed-off-by: Marc-Andre Laperle <malaperle@gmail.com>
This commit is contained in:
parent
25cbbcd5b5
commit
f6d1132d8e
2 changed files with 99 additions and 39 deletions
|
@ -2,7 +2,7 @@ Manifest-Version: 1.0
|
||||||
Bundle-ManifestVersion: 2
|
Bundle-ManifestVersion: 2
|
||||||
Bundle-Name: %pluginName
|
Bundle-Name: %pluginName
|
||||||
Bundle-SymbolicName: org.eclipse.cdt.managedbuilder.core; singleton:=true
|
Bundle-SymbolicName: org.eclipse.cdt.managedbuilder.core; singleton:=true
|
||||||
Bundle-Version: 9.1.0.qualifier
|
Bundle-Version: 9.1.100.qualifier
|
||||||
Bundle-Activator: org.eclipse.cdt.managedbuilder.core.ManagedBuilderCorePlugin
|
Bundle-Activator: org.eclipse.cdt.managedbuilder.core.ManagedBuilderCorePlugin
|
||||||
Bundle-Vendor: %providerName
|
Bundle-Vendor: %providerName
|
||||||
Bundle-Localization: plugin
|
Bundle-Localization: plugin
|
||||||
|
|
|
@ -100,6 +100,56 @@ public abstract class AbstractLanguageSettingsOutputScanner extends LanguageSett
|
||||||
FIND_RESOURCES_CACHE_SIZE);
|
FIND_RESOURCES_CACHE_SIZE);
|
||||||
private HashMap<IProject, LRUCache<IPath, List<IResource>>> findPathInProjectCache = new HashMap<>();
|
private HashMap<IProject, LRUCache<IPath, List<IResource>>> findPathInProjectCache = new HashMap<>();
|
||||||
|
|
||||||
|
//String pathStr, URI baseURI -> URI
|
||||||
|
private static class MappedURIKey {
|
||||||
|
URI baseURI;
|
||||||
|
String pathStr;
|
||||||
|
|
||||||
|
public MappedURIKey(URI baseURI, String pathStr) {
|
||||||
|
super();
|
||||||
|
this.baseURI = baseURI;
|
||||||
|
this.pathStr = pathStr;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
final int prime = 31;
|
||||||
|
int result = 1;
|
||||||
|
result = prime * result + ((baseURI == null) ? 0 : baseURI.hashCode());
|
||||||
|
result = prime * result + ((pathStr == null) ? 0 : pathStr.hashCode());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj)
|
||||||
|
return true;
|
||||||
|
if (obj == null)
|
||||||
|
return false;
|
||||||
|
if (getClass() != obj.getClass())
|
||||||
|
return false;
|
||||||
|
MappedURIKey other = (MappedURIKey) obj;
|
||||||
|
if (baseURI == null) {
|
||||||
|
if (other.baseURI != null)
|
||||||
|
return false;
|
||||||
|
} else if (!baseURI.equals(other.baseURI))
|
||||||
|
return false;
|
||||||
|
if (pathStr == null) {
|
||||||
|
if (other.pathStr != null)
|
||||||
|
return false;
|
||||||
|
} else if (!pathStr.equals(other.pathStr))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Caches the result of determineMappedURI
|
||||||
|
private LRUCache<MappedURIKey, URI> mappedURICache = new LRUCache<>(FIND_RESOURCES_CACHE_SIZE);
|
||||||
|
// Caches the result of getFilesystemLocation
|
||||||
|
private LRUCache<URI, IPath> fileSystemLocationCache = new LRUCache<>(FIND_RESOURCES_CACHE_SIZE);
|
||||||
|
// Caches the result of new File(pathname).exists()
|
||||||
|
private LRUCache<IPath, Boolean> pathExistsCache = new LRUCache<>(FIND_RESOURCES_CACHE_SIZE);
|
||||||
|
|
||||||
/** @since 8.2 */
|
/** @since 8.2 */
|
||||||
protected EFSExtensionProvider efsProvider = null;
|
protected EFSExtensionProvider efsProvider = null;
|
||||||
|
|
||||||
|
@ -498,6 +548,9 @@ public abstract class AbstractLanguageSettingsOutputScanner extends LanguageSett
|
||||||
workspaceRootFindContainersForLocationURICache.clear();
|
workspaceRootFindContainersForLocationURICache.clear();
|
||||||
workspaceRootFindFilesForLocationURICache.clear();
|
workspaceRootFindFilesForLocationURICache.clear();
|
||||||
findPathInProjectCache.clear();
|
findPathInProjectCache.clear();
|
||||||
|
mappedURICache.clear();
|
||||||
|
fileSystemLocationCache.clear();
|
||||||
|
pathExistsCache.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -958,34 +1011,36 @@ public abstract class AbstractLanguageSettingsOutputScanner extends LanguageSett
|
||||||
* @return {@link URI} of the resource
|
* @return {@link URI} of the resource
|
||||||
*/
|
*/
|
||||||
private URI determineMappedURI(String pathStr, URI baseURI) {
|
private URI determineMappedURI(String pathStr, URI baseURI) {
|
||||||
URI uri = null;
|
return mappedURICache.computeIfAbsent(new MappedURIKey(baseURI, pathStr), key -> {
|
||||||
|
URI uri = null;
|
||||||
|
|
||||||
if (baseURI == null) {
|
if (baseURI == null) {
|
||||||
if (new Path(pathStr).isAbsolute()) {
|
if (new Path(pathStr).isAbsolute()) {
|
||||||
uri = resolvePathFromBaseLocation(pathStr, Path.ROOT);
|
uri = resolvePathFromBaseLocation(pathStr, Path.ROOT);
|
||||||
}
|
}
|
||||||
} else if (baseURI.getScheme().equals(EFS.SCHEME_FILE)) {
|
} else if (baseURI.getScheme().equals(EFS.SCHEME_FILE)) {
|
||||||
// location on the local file-system
|
// location on the local file-system
|
||||||
IPath baseLocation = org.eclipse.core.filesystem.URIUtil.toPath(baseURI);
|
IPath baseLocation = org.eclipse.core.filesystem.URIUtil.toPath(baseURI);
|
||||||
// careful not to use Path here but 'pathStr' as String as we want to properly navigate symlinks
|
// careful not to use Path here but 'pathStr' as String as we want to properly navigate symlinks
|
||||||
uri = resolvePathFromBaseLocation(pathStr, baseLocation);
|
uri = resolvePathFromBaseLocation(pathStr, baseLocation);
|
||||||
} else {
|
} else {
|
||||||
// location on a remote file-system
|
// location on a remote file-system
|
||||||
IPath path = new Path(pathStr); // use canonicalized path here, in particular replace all '\' with '/' for Windows paths
|
IPath path = new Path(pathStr); // use canonicalized path here, in particular replace all '\' with '/' for Windows paths
|
||||||
URI remoteUri = efsProvider.append(baseURI, path.toString());
|
URI remoteUri = efsProvider.append(baseURI, path.toString());
|
||||||
if (remoteUri != null) {
|
if (remoteUri != null) {
|
||||||
String localPath = efsProvider.getMappedPath(remoteUri);
|
String localPath = efsProvider.getMappedPath(remoteUri);
|
||||||
if (localPath != null) {
|
if (localPath != null) {
|
||||||
uri = org.eclipse.core.filesystem.URIUtil.toURI(localPath);
|
uri = org.eclipse.core.filesystem.URIUtil.toURI(localPath);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (uri == null) {
|
if (uri == null) {
|
||||||
// if everything fails just wrap string to URI
|
// if everything fails just wrap string to URI
|
||||||
uri = org.eclipse.core.filesystem.URIUtil.toURI(pathStr);
|
uri = org.eclipse.core.filesystem.URIUtil.toURI(pathStr);
|
||||||
}
|
}
|
||||||
return uri;
|
return uri;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1103,22 +1158,24 @@ public abstract class AbstractLanguageSettingsOutputScanner extends LanguageSett
|
||||||
if (uri == null)
|
if (uri == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
String pathStr = efsProvider.getMappedPath(uri);
|
return fileSystemLocationCache.computeIfAbsent(uri, (k) -> {
|
||||||
uri = org.eclipse.core.filesystem.URIUtil.toURI(pathStr);
|
String pathStr = efsProvider.getMappedPath(uri);
|
||||||
|
URI resUri = org.eclipse.core.filesystem.URIUtil.toURI(pathStr);
|
||||||
|
|
||||||
if (uri != null && uri.isAbsolute()) {
|
if (resUri != null && resUri.isAbsolute()) {
|
||||||
try {
|
try {
|
||||||
File file = new java.io.File(uri);
|
File file = new java.io.File(resUri);
|
||||||
String canonicalPathStr = file.getCanonicalPath();
|
String canonicalPathStr = file.getCanonicalPath();
|
||||||
if (new Path(pathStr).getDevice() == null) {
|
if (new Path(pathStr).getDevice() == null) {
|
||||||
return new Path(canonicalPathStr).setDevice(null);
|
return new Path(canonicalPathStr).setDevice(null);
|
||||||
|
}
|
||||||
|
return new Path(canonicalPathStr);
|
||||||
|
} catch (Exception e) {
|
||||||
|
ManagedBuilderCorePlugin.log(e);
|
||||||
}
|
}
|
||||||
return new Path(canonicalPathStr);
|
|
||||||
} catch (Exception e) {
|
|
||||||
ManagedBuilderCorePlugin.log(e);
|
|
||||||
}
|
}
|
||||||
}
|
return null;
|
||||||
return null;
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1199,7 +1256,10 @@ public abstract class AbstractLanguageSettingsOutputScanner extends LanguageSett
|
||||||
IPath location = getFilesystemLocation(uri);
|
IPath location = getFilesystemLocation(uri);
|
||||||
if (location != null) {
|
if (location != null) {
|
||||||
String loc = location.toString();
|
String loc = location.toString();
|
||||||
if (new File(loc).exists()) {
|
boolean exists = pathExistsCache.computeIfAbsent(location, (s) -> {
|
||||||
|
return new File(loc).exists();
|
||||||
|
});
|
||||||
|
if (exists) {
|
||||||
return optionParser.createEntry(loc, loc, flag);
|
return optionParser.createEntry(loc, loc, flag);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue