aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhilipp Thun2011-01-27 15:49:42 (EST)
committerChris Aniszczyk2011-01-31 11:06:43 (EST)
commitc03562f2202231d55e84eb761bb1462fd69a584a (patch)
tree36a2f5ce8825955d065eec7b572e0772749fba21
parent29113c22054efe10092ce8ff5d6ea9710e325962 (diff)
downloadegit-c03562f2202231d55e84eb761bb1462fd69a584a.zip
egit-c03562f2202231d55e84eb761bb1462fd69a584a.tar.gz
egit-c03562f2202231d55e84eb761bb1462fd69a584a.tar.bz2
Cache file length as session property for each resourcerefs/changes/06/2306/4
When comparing DirCacheEntries to ResourceEntries it is checked whether they differ with regards to modification timestamp and file length. Whereas the timestamp is available for all IResources and thus cached by Eclipse, the file length needed to be retrieved from the actual file on disk for every comparison. With this change a session resource property is introduced that stores the file length once it has been retrieved from disk. The property is removed whenever a resource changes (by eventing). Using persistent properties for this scenario first seemed to be an even better idea, but as these properties are stored on disk by Eclipse there was a huge performance degradation when filling the cache, i.e. during the first traversal of a TreeWalk containing a ContainerTreeIterator (e.g. after startup of Eclipse). So with this change there is no improvement for the performance of decorating a project for the first time after Eclipse starts up, but every refresh on project level as well as all decorations of (deep) folder structures are significantly improved. Furthermore the ContainerTreeIterator is also used in other use cases, i.e. when opening the commit dialog. See bug 325393 for performance results. Bug: 325393 Change-Id: I7fd99c3cc5f5933a431835cc7019a8a65826edc0 Signed-off-by: Philipp Thun <philipp.thun@sap.com> Signed-off-by: Chris Aniszczyk <caniszczyk@gmail.com>
-rw-r--r--org.eclipse.egit.core/src/org/eclipse/egit/core/ContainerTreeIterator.java75
1 files changed, 70 insertions, 5 deletions
diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/ContainerTreeIterator.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/ContainerTreeIterator.java
index abb3f04..2e348f7 100644
--- a/org.eclipse.egit.core/src/org/eclipse/egit/core/ContainerTreeIterator.java
+++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/ContainerTreeIterator.java
@@ -16,8 +16,14 @@ import java.io.InputStream;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceChangeEvent;
+import org.eclipse.core.resources.IResourceChangeListener;
+import org.eclipse.core.resources.IResourceDelta;
+import org.eclipse.core.resources.IResourceDeltaVisitor;
import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.QualifiedName;
import org.eclipse.egit.core.project.RepositoryMapping;
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.eclipse.jgit.lib.Constants;
@@ -48,6 +54,10 @@ import org.eclipse.team.core.Team;
* @see org.eclipse.jgit.treewalk.TreeWalk
*/
public class ContainerTreeIterator extends WorkingTreeIterator {
+
+ private static final QualifiedName FILE_LENGTH_KEY = new QualifiedName(
+ Activator.getPluginId(), "fileLength"); //$NON-NLS-1$
+
private static String computePrefix(final IContainer base) {
final RepositoryMapping rm = RepositoryMapping.getMapping(base);
if (rm == null)
@@ -74,6 +84,7 @@ public class ContainerTreeIterator extends WorkingTreeIterator {
*/
public ContainerTreeIterator(final Repository repository, final IContainer base) {
super(computePrefix(base), repository.getConfig().get(WorkingTreeOptions.KEY));
+ registerRCL();
node = base;
init(entries());
}
@@ -93,6 +104,7 @@ public class ContainerTreeIterator extends WorkingTreeIterator {
*/
public ContainerTreeIterator(final Repository repository, final IWorkspaceRoot root) {
super("", repository.getConfig().get(WorkingTreeOptions.KEY)); //$NON-NLS-1$
+ registerRCL();
node = root;
init(entries());
}
@@ -115,6 +127,7 @@ public class ContainerTreeIterator extends WorkingTreeIterator {
public ContainerTreeIterator(final WorkingTreeIterator p,
final IContainer base) {
super(p);
+ registerRCL();
node = base;
init(entries());
}
@@ -160,7 +173,7 @@ public class ContainerTreeIterator extends WorkingTreeIterator {
}
private boolean isEntryIgnoredByTeamProvider(IResource resource) {
- if (resource instanceof IWorkspaceRoot)
+ if (resource.getType() == IResource.ROOT)
return false;
if (Team.isIgnoredHint(resource))
return true;
@@ -220,10 +233,28 @@ public class ContainerTreeIterator extends WorkingTreeIterator {
@Override
public long getLength() {
if (length < 0) {
- if (rsrc instanceof IFile)
- length = asFile().length();
- else
+ if (rsrc.getType() == IResource.FILE) {
+ Long fileLength = null;
+ try {
+ fileLength = (Long) rsrc
+ .getSessionProperty(FILE_LENGTH_KEY);
+ } catch (CoreException e) {
+ // Ignore
+ }
+ if (fileLength != null) {
+ length = fileLength.longValue();
+ } else {
+ length = asFile().length();
+ try {
+ rsrc.setSessionProperty(FILE_LENGTH_KEY, new Long(
+ length));
+ } catch (CoreException e) {
+ // Ignore
+ }
+ }
+ } else {
length = 0;
+ }
}
return length;
}
@@ -235,7 +266,7 @@ public class ContainerTreeIterator extends WorkingTreeIterator {
@Override
public InputStream openInputStream() throws IOException {
- if (rsrc instanceof IFile) {
+ if (rsrc.getType() == IResource.FILE) {
try {
return ((IFile) rsrc).getContents(true);
} catch (CoreException err) {
@@ -260,4 +291,38 @@ public class ContainerTreeIterator extends WorkingTreeIterator {
return ((IFile) rsrc).getLocation().toFile();
}
}
+
+ private static final IResourceChangeListener rcl = new RCL();
+
+ private static class RCL implements IResourceChangeListener {
+
+ // Remove 'fileLength' property for changed resources
+ public void resourceChanged(IResourceChangeEvent event) {
+ try {
+ event.getDelta().accept(new IResourceDeltaVisitor() {
+
+ public boolean visit(IResourceDelta delta)
+ throws CoreException {
+ final IResource resource = delta.getResource();
+ if (resource != null
+ && resource.getType() == IResource.FILE)
+ try {
+ resource.setSessionProperty(FILE_LENGTH_KEY,
+ null);
+ } catch (CoreException e) {
+ // Ignore
+ }
+ return true;
+ }
+ }, true);
+ } catch (CoreException e) {
+ // Ignore
+ }
+ }
+ }
+
+ private static void registerRCL() {
+ ResourcesPlugin.getWorkspace().addResourceChangeListener(rcl,
+ IResourceChangeEvent.POST_CHANGE);
+ }
}