diff options
| author | Philipp Thun | 2011-01-27 20:49:42 +0000 |
|---|---|---|
| committer | Chris Aniszczyk | 2011-01-31 16:06:43 +0000 |
| commit | c03562f2202231d55e84eb761bb1462fd69a584a (patch) | |
| tree | 36a2f5ce8825955d065eec7b572e0772749fba21 | |
| parent | 29113c22054efe10092ce8ff5d6ea9710e325962 (diff) | |
| download | egit-c03562f2202231d55e84eb761bb1462fd69a584a.tar.gz egit-c03562f2202231d55e84eb761bb1462fd69a584a.tar.xz egit-c03562f2202231d55e84eb761bb1462fd69a584a.zip | |
Cache file length as session property for each resource
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.java | 75 |
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 abb3f04a11..2e348f75c9 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); + } } |
