Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Sohn2012-05-10 14:41:22 +0000
committerMatthias Sohn2012-06-04 14:15:42 +0000
commit53ff64118482ecdc7221d9896c0717dbe9dab308 (patch)
tree2eea63a0c05a860a39f87f79f1036e570f0d025e
parente01d5bd9ca0c0fe8969a2ec883eadac3404f3d05 (diff)
downloadegit-53ff64118482ecdc7221d9896c0717dbe9dab308.tar.gz
egit-53ff64118482ecdc7221d9896c0717dbe9dab308.tar.xz
egit-53ff64118482ecdc7221d9896c0717dbe9dab308.zip
Load history incrementally
Loading history incrementally can drastically reduce memory consumption and the time needed to render the part of the history the user is interested in. Most often only the most recent part of the history is needed. Hence load only one batch of 256 commits initially and keep the GenerateHistoryJob in order to incrementally load the next batch when the user has scrolled down half of the loading batch size (128 commits). JGit-Dependency: Id3b97d88d3b4b2d67561b11f8810cb88fe040823 Change-Id: Ibc88d589ea2a5f233cd65c203bde9187c122a277 Signed-off-by: Matthias Sohn <matthias.sohn@sap.com> Signed-off-by: Stefan Lay <stefan.lay@sap.com>
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/CommitGraphTable.java47
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/CommitSelectionDialog.java4
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/GenerateHistoryJob.java88
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/GitHistoryPage.java67
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/TableLoader.java26
5 files changed, 159 insertions, 73 deletions
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/CommitGraphTable.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/CommitGraphTable.java
index 139cc9c5ed..ed684542a0 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/CommitGraphTable.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/CommitGraphTable.java
@@ -3,9 +3,8 @@
* Copyright (C) 2007, Robin Rosenberg <robin.rosenberg@dewire.com>
* Copyright (C) 2008, Roger C. Soares <rogersoares@intelinet.com.br>
* Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
- * Copyright (C) 2011, Mathias Kinzler <mathias.kinzler@sap.com>
- * Copyright (C) 2011, Matthias Sohn <matthias.sohn@sap.com>
- * Copyright (C) 2012, Mathias Kinzler <mathias.kinzler@sap.com>
+ * Copyright (C) 2011-2012, Mathias Kinzler <mathias.kinzler@sap.com>
+ * Copyright (C) 2011-2012, Matthias Sohn <matthias.sohn@sap.com>
* Copyright (C) 2012, Robin Stocker <robin@nibor.org>
*
* All rights reserved. This program and the accompanying materials
@@ -39,6 +38,7 @@ import org.eclipse.egit.ui.UIPreferences;
import org.eclipse.egit.ui.UIText;
import org.eclipse.egit.ui.UIUtils;
import org.eclipse.egit.ui.internal.history.command.HistoryViewCommands;
+import org.eclipse.egit.ui.internal.trace.GitTraceLocation;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.MenuManager;
@@ -136,6 +136,8 @@ class CommitGraphTable {
private SWTCommitList allCommits;
+ private int allCommitsLength = 0;
+
// used for resolving PlotCommit objects by ids
private HashMap<String, PlotCommit> commitsMap = null;
@@ -151,15 +153,33 @@ class CommitGraphTable {
private GraphLabelProvider graphLabelProvider;
- CommitGraphTable(Composite parent) {
+ private final TableLoader tableLoader;
+
+ private boolean trace = GitTraceLocation.HISTORYVIEW.isActive();
+
+ CommitGraphTable(Composite parent, final TableLoader loader) {
nFont = UIUtils.getFont(UIPreferences.THEME_CommitGraphNormalFont);
hFont = highlightFont();
+ tableLoader = loader;
- Table rawTable = new Table(parent, SWT.MULTI | SWT.H_SCROLL
+ final Table rawTable = new Table(parent, SWT.MULTI | SWT.H_SCROLL
| SWT.V_SCROLL | SWT.BORDER | SWT.FULL_SELECTION | SWT.VIRTUAL);
rawTable.setHeaderVisible(true);
rawTable.setLinesVisible(false);
rawTable.setFont(nFont);
+ rawTable.addListener(SWT.SetData, new Listener() {
+ public void handleEvent(Event event) {
+ if (tableLoader != null) {
+ TableItem item = (TableItem) event.item;
+ int index = rawTable.indexOf(item);
+ if (trace)
+ GitTraceLocation.getTrace().trace(
+ GitTraceLocation.HISTORYVIEW.getLocation(),
+ "Item " + index); //$NON-NLS-1$
+ tableLoader.loadItem(index);
+ }
+ }
+ });
final TableLayout layout = new TableLayout();
rawTable.setLayout(layout);
@@ -226,8 +246,8 @@ class CommitGraphTable {
}
CommitGraphTable(final Composite parent, final IPageSite site,
- final MenuManager menuMgr) {
- this(parent);
+ final MenuManager menuMgr, final TableLoader loader) {
+ this(parent, loader);
final IAction selectAll = createStandardAction(ActionFactory.SELECT_ALL);
getControl().addFocusListener(new FocusListener() {
@@ -303,6 +323,8 @@ class CommitGraphTable {
table.setSelection(new StructuredSelection(c), true);
else if (commitsMap != null) {
PlotCommit swtCommit = commitsMap.get(c.getId().name());
+ if (swtCommit == null && tableLoader != null)
+ tableLoader.loadCommit(c);
if (swtCommit != null)
table.setSelection(new StructuredSelection(swtCommit), true);
}
@@ -350,21 +372,28 @@ class CommitGraphTable {
}
void setInput(final RevFlag hFlag, final SWTCommitList list,
- final SWTCommit[] asArray, HistoryPageInput input) {
+ final SWTCommit[] asArray, HistoryPageInput input, boolean keepPosition) {
+ int topIndex = -1;
+ if (keepPosition)
+ topIndex = table.getTable().getTopIndex();
setHistoryPageInput(input);
final SWTCommitList oldList = allCommits;
if (oldList != null && oldList != list)
oldList.dispose();
highlight = hFlag;
allCommits = list;
+ int newAllCommitsLength = allCommits.size();
table.setInput(asArray);
if (asArray != null && asArray.length > 0) {
- if (oldList != list)
+ if (oldList != list || allCommitsLength < newAllCommitsLength)
initCommitsMap();
} else
table.getTable().deselectAll();
+ allCommitsLength = newAllCommitsLength;
if (commitToShow != null)
selectCommit(commitToShow);
+ if (keepPosition)
+ table.getTable().setTopIndex(topIndex);
}
void setHistoryPageInput(HistoryPageInput input) {
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/CommitSelectionDialog.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/CommitSelectionDialog.java
index eb2df25863..a025312203 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/CommitSelectionDialog.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/CommitSelectionDialog.java
@@ -73,7 +73,7 @@ public class CommitSelectionDialog extends TitleAreaDialog {
Composite main = new Composite(parent, SWT.NONE);
main.setLayout(new GridLayout(1, false));
GridDataFactory.fillDefaults().grab(true, true).applyTo(main);
- table = new CommitGraphTable(main);
+ table = new CommitGraphTable(main, null);
table.getTableView().addSelectionChangedListener(
new ISelectionChangedListener() {
public void selectionChanged(SelectionChangedEvent event) {
@@ -198,7 +198,7 @@ public class CommitSelectionDialog extends TitleAreaDialog {
.toString()));
setMessage(UIText.CommitSelectionDialog_DialogMessage);
table.setInput(highlightFlag, allCommits, allCommits
- .toArray(new SWTCommit[allCommits.size()]), null);
+ .toArray(new SWTCommit[allCommits.size()]), null, true);
}
private void markStartAllRefs(RevWalk currentWalk, String prefix)
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/GenerateHistoryJob.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/GenerateHistoryJob.java
index 822624b913..8d95043898 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/GenerateHistoryJob.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/GenerateHistoryJob.java
@@ -1,5 +1,6 @@
/*******************************************************************************
* Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
+ * Copyright (C) 2012, Matthias Sohn <matthias.sohn@sap.com>
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
@@ -24,6 +25,7 @@ import org.eclipse.egit.ui.UIText;
import org.eclipse.egit.ui.internal.trace.GitTraceLocation;
import org.eclipse.jgit.revwalk.RevFlag;
import org.eclipse.jgit.revwalk.RevWalk;
+import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
@@ -31,39 +33,41 @@ import org.eclipse.swt.widgets.Display;
class GenerateHistoryJob extends Job {
private static final int BATCH_SIZE = 256;
- private final int maxCommits = Activator.getDefault().getPreferenceStore()
- .getInt(UIPreferences.HISTORY_MAX_NUM_COMMITS);
-
private final GitHistoryPage page;
- private final SWTCommitList allCommits;
+ private final SWTCommitList loadedCommits;
- private int lastUpdateCnt;
+ private int itemToLoad = 1;
+
+ private RevCommit commitToLoad;
+
+ private RevCommit commitToShow;
- private long lastUpdateAt;
+ private int lastUpdateCnt;
private boolean trace;
private final RevWalk walk;
+ private RevFlag highlightFlag;
+
GenerateHistoryJob(final GitHistoryPage ghp, Control control, RevWalk walk) {
super(NLS.bind(UIText.HistoryPage_refreshJob, Activator.getDefault()
.getRepositoryUtil().getRepositoryName(
ghp.getInputInternal().getRepository())));
page = ghp;
this.walk = walk;
- allCommits = new SWTCommitList(control);
- allCommits.source(walk);
+ highlightFlag = walk.newFlag("highlight"); //$NON-NLS-1$
+ loadedCommits = new SWTCommitList(control);
+ loadedCommits.source(walk);
trace = GitTraceLocation.HISTORYVIEW.isActive();
}
- public RevWalk getWalk() {
- return walk;
- }
-
@Override
protected IStatus run(final IProgressMonitor monitor) {
IStatus status = Status.OK_STATUS;
+ int maxCommits = Activator.getDefault().getPreferenceStore()
+ .getInt(UIPreferences.HISTORY_MAX_NUM_COMMITS);
boolean incomplete = false;
try {
if (trace)
@@ -71,40 +75,47 @@ class GenerateHistoryJob extends Job {
GitTraceLocation.HISTORYVIEW.getLocation());
try {
for (;;) {
- final int oldsz = allCommits.size();
+ int oldsz = loadedCommits.size();
if (trace)
GitTraceLocation.getTrace().trace(
GitTraceLocation.HISTORYVIEW.getLocation(),
"Filling commit list"); //$NON-NLS-1$
// ensure that filling (here) and reading (CommitGraphTable)
// the commit list is thread safe
- synchronized (allCommits) {
- allCommits.fillTo(oldsz + BATCH_SIZE - 1);
+ synchronized (loadedCommits) {
+ if (commitToLoad != null) {
+ loadedCommits.fillTo(commitToLoad, maxCommits);
+ commitToShow = commitToLoad;
+ commitToLoad = null;
+ } else
+ loadedCommits.fillTo(oldsz + BATCH_SIZE - 1);
}
if (monitor.isCanceled())
return Status.CANCEL_STATUS;
- if (maxCommits > 0 && allCommits.size() > maxCommits)
+ final boolean loadIncrementally = !Activator.getDefault().getPreferenceStore()
+ .getBoolean(UIPreferences.RESOURCEHISTORY_SHOW_FINDTOOLBAR);
+ if (loadedCommits.size() > itemToLoad + (BATCH_SIZE / 2) + 1 && loadIncrementally)
+ break;
+ if (maxCommits > 0 && loadedCommits.size() > maxCommits)
incomplete = true;
- if (incomplete || oldsz == allCommits.size())
+ if (incomplete || oldsz == loadedCommits.size())
break;
- if (allCommits.size() != 1)
+ if (loadedCommits.size() != 1)
monitor.setTaskName(MessageFormat
.format(UIText.GenerateHistoryJob_taskFoundMultipleCommits,
- Integer.valueOf(allCommits.size())));
+ Integer.valueOf(loadedCommits.size())));
else
monitor.setTaskName(UIText.GenerateHistoryJob_taskFoundSingleCommit);
-
- final long now = System.currentTimeMillis();
- if (now - lastUpdateAt < 2000 && lastUpdateCnt > 0)
- continue;
- updateUI(incomplete);
- lastUpdateAt = now;
}
} catch (IOException e) {
status = new Status(IStatus.ERROR, Activator.getPluginId(),
UIText.GenerateHistoryJob_errorComputingHistory, e);
}
+ if (trace)
+ GitTraceLocation.getTrace().trace(
+ GitTraceLocation.HISTORYVIEW.getLocation(),
+ "Loaded " + loadedCommits.size() + " commits"); //$NON-NLS-1$ //$NON-NLS-2$
updateUI(incomplete);
} finally {
monitor.done();
@@ -115,19 +126,19 @@ class GenerateHistoryJob extends Job {
return status;
}
- void updateUI(boolean incomplete) {
+ private void updateUI(boolean incomplete) {
if (trace)
GitTraceLocation.getTrace().traceEntry(
GitTraceLocation.HISTORYVIEW.getLocation());
try {
- if (!incomplete && allCommits.size() == lastUpdateCnt)
+ if (!incomplete && loadedCommits.size() == lastUpdateCnt)
return;
- final SWTCommit[] asArray = new SWTCommit[allCommits.size()];
- allCommits.toArray(asArray);
- RevFlag highlightFlag = walk.newFlag("highlight"); //$NON-NLS-1$
- page.showCommitList(this, allCommits, asArray, incomplete, highlightFlag);
- lastUpdateCnt = allCommits.size();
+ final SWTCommit[] asArray = new SWTCommit[loadedCommits.size()];
+ loadedCommits.toArray(asArray);
+ page.showCommitList(this, loadedCommits, asArray, commitToShow, incomplete, highlightFlag);
+ commitToShow = null;
+ lastUpdateCnt = loadedCommits.size();
} finally {
if (trace)
GitTraceLocation.getTrace().traceExit(
@@ -153,7 +164,7 @@ class GenerateHistoryJob extends Job {
Display.getDefault().asyncExec(new Runnable() {
public void run() {
- allCommits.dispose();
+ loadedCommits.dispose();
}
});
}
@@ -165,4 +176,15 @@ class GenerateHistoryJob extends Job {
return super.belongsTo(family);
}
+ void setLoadHint(final int index) {
+ itemToLoad = index;
+ }
+
+ void setLoadHint(final RevCommit c) {
+ commitToLoad = c;
+ }
+
+ int loadMoreItemsThreshold() {
+ return loadedCommits.size() - (BATCH_SIZE / 2);
+ }
}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/GitHistoryPage.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/GitHistoryPage.java
index 06c086d9eb..f283a74485 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/GitHistoryPage.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/GitHistoryPage.java
@@ -3,7 +3,7 @@
* Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
* Copyright (c) 2010, Stefan Lay <stefan.lay@sap.com>
* Copyright (C) 2010, Mathias Kinzler <mathias.kinzler@sap.com>
- * Copyright (C) 2010-2011, Matthias Sohn <matthias.sohn@sap.com>
+ * Copyright (C) 2010-2012, Matthias Sohn <matthias.sohn@sap.com>
* Copyright (C) 2012, Daniel megert <daniel_megert@ch.ibm.com>
*
* All rights reserved. This program and the accompanying materials
@@ -24,10 +24,8 @@ import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
-import org.eclipse.core.runtime.jobs.IJobChangeEvent;
import org.eclipse.core.runtime.jobs.ISchedulingRule;
import org.eclipse.core.runtime.jobs.Job;
-import org.eclipse.core.runtime.jobs.JobChangeAdapter;
import org.eclipse.egit.core.AdapterUtils;
import org.eclipse.egit.core.project.RepositoryMapping;
import org.eclipse.egit.ui.Activator;
@@ -115,7 +113,9 @@ import org.eclipse.ui.progress.IWorkbenchSiteProgressService;
/** Graphical commit history viewer. */
public class GitHistoryPage extends HistoryPage implements RefsChangedListener,
- ISchedulingRule {
+ ISchedulingRule, TableLoader {
+
+ private static final int INITIAL_ITEM = -1;
/** actions used in GitHistoryPage **/
private static class GitHistoryPageActions {
@@ -739,7 +739,7 @@ public class GitHistoryPage extends HistoryPage implements RefsChangedListener,
graphDetailSplit = new SashForm(historyControl, SWT.VERTICAL);
GridDataFactory.fillDefaults().grab(true, true).applyTo(
graphDetailSplit);
- graph = new CommitGraphTable(graphDetailSplit, getSite(), popupMgr);
+ graph = new CommitGraphTable(graphDetailSplit, getSite(), popupMgr, this);
graph.setRelativeDate(isShowingRelativeDates());
graph.setShowEmailAddresses(isShowingEmailAddresses());
@@ -1431,7 +1431,7 @@ public class GitHistoryPage extends HistoryPage implements RefsChangedListener,
}
void showCommitList(final Job j, final SWTCommitList list,
- final SWTCommit[] asArray, final boolean incomplete, final RevFlag highlightFlag) {
+ final SWTCommit[] asArray, final RevCommit toSelect, final boolean incomplete, final RevFlag highlightFlag) {
if (trace)
GitTraceLocation.getTrace().traceEntry(
GitTraceLocation.HISTORYVIEW.getLocation(),
@@ -1442,7 +1442,9 @@ public class GitHistoryPage extends HistoryPage implements RefsChangedListener,
graph.getControl().getDisplay().asyncExec(new Runnable() {
public void run() {
if (!graph.getControl().isDisposed() && job == j) {
- graph.setInput(highlightFlag, list, asArray, input);
+ graph.setInput(highlightFlag, list, asArray, input, true);
+ if (toSelect != null)
+ graph.selectCommit(toSelect);
if (trace)
GitTraceLocation.getTrace().trace(
GitTraceLocation.HISTORYVIEW.getLocation(),
@@ -1508,7 +1510,7 @@ public class GitHistoryPage extends HistoryPage implements RefsChangedListener,
setupFileViewer(walk, db, paths);
setupCommentViewer(db);
- scheduleNewGenerateHistoryJob(walk);
+ loadHistory(INITIAL_ITEM, walk);
} else
// needed for context menu and double click
graph.setHistoryPageInput(input);
@@ -1779,31 +1781,38 @@ public class GitHistoryPage extends HistoryPage implements RefsChangedListener,
return true;
}
- private void scheduleNewGenerateHistoryJob(RevWalk walk) {
- final GenerateHistoryJob rj = new GenerateHistoryJob(this,
- graph.getControl(), walk);
- rj.setRule(this);
- rj.addJobChangeListener(new JobChangeAdapter() {
- @Override
- public void done(final IJobChangeEvent event) {
- rj.getWalk().release();
- final Control graphctl = graph.getControl();
- if (job != rj || graphctl.isDisposed())
- return;
- graphctl.getDisplay().asyncExec(new Runnable() {
- public void run() {
- if (job == rj)
- job = null;
- }
- });
- }
- });
- job = rj;
+ public void loadItem(int item) {
+ if (job == null || job.loadMoreItemsThreshold() < item)
+ loadHistory(item, null);
+ }
+
+ public void loadCommit(RevCommit c) {
+ if (job == null)
+ return;
+ job.setLoadHint(c);
+ if (trace)
+ GitTraceLocation.getTrace().trace(
+ GitTraceLocation.HISTORYVIEW.getLocation(),
+ "Scheduling GenerateHistoryJob"); //$NON-NLS-1$
+ schedule(job);
+ }
+
+ /**
+ * Load history items incrementally
+ * @param itemToLoad hint for index of item that should be loaded
+ * @param walk the revwalk, used only if itemToLoad == INITIAL_ITEM
+ */
+ private void loadHistory(final int itemToLoad, RevWalk walk) {
+ if (itemToLoad == INITIAL_ITEM) {
+ job = new GenerateHistoryJob(this, graph.getControl(), walk);
+ job.setRule(this);
+ }
+ job.setLoadHint(itemToLoad);
if (trace)
GitTraceLocation.getTrace().trace(
GitTraceLocation.HISTORYVIEW.getLocation(),
"Scheduling GenerateHistoryJob"); //$NON-NLS-1$
- schedule(rj);
+ schedule(job);
}
private IWorkbenchPartSite getPartSite() {
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/TableLoader.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/TableLoader.java
new file mode 100644
index 0000000000..1c0f377804
--- /dev/null
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/TableLoader.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (C) 2012, Matthias Sohn <matthias.sohn@sap.com>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.egit.ui.internal.history;
+
+import org.eclipse.jgit.revwalk.RevCommit;
+
+/**
+ * Callback interface for incrementally loading table items
+ */
+public interface TableLoader {
+ /**
+ * @param index hint for index of table item to be loaded
+ */
+ void loadItem(int index);
+
+ /**
+ * @param c commit to be loaded
+ */
+ void loadCommit(RevCommit c);
+}

Back to the top