Skip to content

Commit 2b92f87

Browse files
authored
Merge pull request #9324 from OndroMih/ondromih-git-commit-dlg-optimization-skip-no-update
Speed up loading file statuses in Git commit dialog by batching events and skipping events for up-to-date files
2 parents 26cc860 + 642c71b commit 2b92f87

7 files changed

Lines changed: 169 additions & 127 deletions

File tree

ide/git/nbproject/project.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
# specific language governing permissions and limitations
1616
# under the License.
1717
javac.compilerargs=-Xlint
18-
javac.release=17
18+
javac.release=21
1919
nbm.homepage=http://netbeans.org/projects/versioncontrol/pages/Git_main
2020
nbm.module.author=Ondrej Vrabec
2121
nbm.needs.restart=true

ide/git/src/org/netbeans/modules/git/FileStatusCache.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
public class FileStatusCache {
5858

5959
public static final String PROP_FILE_STATUS_CHANGED = "status.changed"; // NOI18N
60+
public static final String PROP_FILES_STATUS_CHANGED = "status.changed.batch"; // NOI18N
6061

6162
private final CacheIndex conflictedFiles, modifiedFiles, ignoredFiles;
6263
private static final Logger LOG = Logger.getLogger("org.netbeans.modules.git.status.cache"); //NOI18N
@@ -562,6 +563,7 @@ private void refreshStatusesBatch (Map<File, GitStatus> interestingFiles) {
562563
boolean fireEvent = true;
563564
current = getInfo(file);
564565
fi = checkForIgnore(fi, current, file);
566+
boolean upToDateOnFirstLoad = current == null && fi.getStatus().equals(EnumSet.of(Status.UPTODATE));
565567
if (equivalent(fi, current)) {
566568
// no need to fire an event
567569
if (Utilities.isWindows() || Utilities.isMac()) {
@@ -570,6 +572,10 @@ private void refreshStatusesBatch (Map<File, GitStatus> interestingFiles) {
570572
} else {
571573
continue;
572574
}
575+
} else if (upToDateOnFirstLoad) {
576+
// file is up-to-date and not yet in cache: UPTODATE is the implicit default,
577+
// no cache update or event needed
578+
continue;
573579
}
574580
boolean addToIndex = updateCachedValue(fi, file);
575581
indexUpdates.add(new IndexUpdateItem(file, fi, addToIndex));
@@ -579,8 +585,8 @@ private void refreshStatusesBatch (Map<File, GitStatus> interestingFiles) {
579585
}
580586
updateIndexBatch(indexUpdates);
581587
}
582-
for (ChangedEvent event : events) {
583-
fireFileStatusChanged(event);
588+
if (!events.isEmpty()) {
589+
listenerSupport.firePropertyChange(PROP_FILES_STATUS_CHANGED, null, events);
584590
}
585591
}
586592

ide/git/src/org/netbeans/modules/git/GitVCS.java

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
import java.beans.PropertyChangeListener;
2424
import java.util.MissingResourceException;
2525
import java.io.File;
26+
import java.util.HashSet;
27+
import java.util.List;
2628
import java.util.Set;
2729
import java.util.logging.Logger;
2830
import java.util.prefs.PreferenceChangeEvent;
@@ -38,17 +40,17 @@
3840
* @author ondra
3941
*/
4042
@VersioningSystem.Registration(
41-
displayName="#CTL_Git_DisplayName",
42-
menuLabel="#CTL_Git_MainMenu",
43-
metadataFolderNames={".git"},
43+
displayName="#CTL_Git_DisplayName",
44+
menuLabel="#CTL_Git_MainMenu",
45+
metadataFolderNames={".git"},
4446
actionsCategory="Git"
4547
)
4648
public class GitVCS extends VersioningSystem implements PropertyChangeListener, PreferenceChangeListener {
4749

4850
private static final Logger LOG = Logger.getLogger("org.netbeans.modules.git.GitVCS"); //NOI18N
4951

5052
public GitVCS() {
51-
putProperty(PROP_DISPLAY_NAME, getDisplayName());
53+
putProperty(PROP_DISPLAY_NAME, getDisplayName());
5254
putProperty(PROP_MENU_LABEL, org.openide.util.NbBundle.getMessage(GitVCS.class, "CTL_Git_MainMenu")); // NOI18N
5355
GitModuleConfig.getDefault().getPreferences().addPreferenceChangeListener(this);
5456
Git.getInstance().registerGitVCS(this);
@@ -77,7 +79,7 @@ public void getOriginalFile (File workingCopy, File originalFile) {
7779
public File getTopmostManagedAncestor(File file) {
7880
return Git.getInstance().getTopmostManagedAncestor(file);
7981
}
80-
82+
8183
@Override
8284
public CollocationQueryImplementation getCollocationQueryImplementation() {
8385
return collocationQueryImplementation;
@@ -111,6 +113,13 @@ public void propertyChange(PropertyChangeEvent event) {
111113
if (event.getPropertyName().equals(FileStatusCache.PROP_FILE_STATUS_CHANGED)) {
112114
FileStatusCache.ChangedEvent changedEvent = (FileStatusCache.ChangedEvent) event.getNewValue();
113115
fireStatusChanged(changedEvent.getFile());
116+
} else if (event.getPropertyName().equals(FileStatusCache.PROP_FILES_STATUS_CHANGED)) {
117+
List<FileStatusCache.ChangedEvent> changedEvents = (List<FileStatusCache.ChangedEvent>) event.getNewValue();
118+
Set<File> files = HashSet.newHashSet(changedEvents.size());
119+
for (FileStatusCache.ChangedEvent e : changedEvents) {
120+
files.add(e.getFile());
121+
}
122+
fireStatusChanged(files);
114123
} else if (event.getPropertyName().equals(Git.PROP_ANNOTATIONS_CHANGED)) {
115124
fireAnnotationsChanged((Set<File>) event.getNewValue());
116125
} else if (event.getPropertyName().equals(Git.PROP_VERSIONED_FILES_CHANGED)) {

ide/git/src/org/netbeans/modules/git/ui/diff/MultiDiffPanelController.java

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ public class MultiDiffPanelController implements ActionListener, PropertyChangeL
196196

197197
private GitProgressSupport statusRefreshSupport;
198198
private PreferenceChangeListener prefList;
199-
199+
200200
private final Revision revisionOriginalLeft;
201201
private final Revision revisionOriginalRight;
202202
private Revision revisionLeft;
@@ -211,7 +211,7 @@ public class MultiDiffPanelController implements ActionListener, PropertyChangeL
211211
private int popupViewIndex;
212212
private int requestedRightLine = -1;
213213
private int requestedLeftLine = -1;
214-
214+
215215
private static final int VIEW_MODE_TABLE = 1;
216216
private static final int VIEW_MODE_TREE = 2;
217217
private int currentSetupDiffLengthChanged;
@@ -270,7 +270,7 @@ public MultiDiffPanelController (File file, Revision rev1, Revision rev2, int re
270270
prepareTask = RP.create(dpt);
271271
prepareTask.schedule(0);
272272
}
273-
273+
274274
private MultiDiffPanelController (VCSContext context, Revision revisionLeft, Revision revisionRight, boolean fixedRevisions) {
275275
this.context = context;
276276
this.revisionLeft = revisionOriginalLeft = revisionLeft;
@@ -315,7 +315,7 @@ private void setActiveComponent (DiffFileViewComponent<DiffNode> fileComponent)
315315
panel.splitPane.setTopComponent(getActiveFileComponent().getComponent());
316316
panel.splitPane.setDividerLocation(gg);
317317
}
318-
318+
319319
private void refreshSelectionCombos () {
320320
if (!fixedRevisions && GitUtils.getRepositoryRoots(context).size() == 1) {
321321
panel.cmbDiffTreeFirst.setEnabled(false);
@@ -432,7 +432,7 @@ public void componentClosed () {
432432
cancelBackgroundTasks();
433433
setups.clear();
434434
editorCookies.clear();
435-
435+
436436
if (list != null) {
437437
Git.getInstance().getFileStatusCache().removePropertyChangeListener(list);
438438
}
@@ -569,7 +569,7 @@ private void initToolbarButtons () {
569569
panel.treeButton.setVisible(false);
570570
}
571571
}
572-
572+
573573
private JComponent getInfoPanelLoading () {
574574
if (infoPanelLoadingFromRepo == null) {
575575
infoPanelLoadingFromRepo = new NoContentPanel(NbBundle.getMessage(MultiDiffPanel.class, "MSG_DiffPanel_NoContent"));
@@ -812,11 +812,11 @@ public void run () {
812812
public void run () {
813813
multiTextDiffSupport = null;
814814
}
815-
815+
816816
});
817817
}
818818
}
819-
819+
820820
private String findEncoding () {
821821
for (File f : actionRoots.getValue()) {
822822
FileObject fo = FileUtil.toFileObject(f);
@@ -861,7 +861,7 @@ private void exportDiff (ByteArrayOutputStream bos) throws GitException {
861861
actionRoots.getKey(), Bundle.MSG_DiffPanel_multiTextualDiff_preparing());
862862
}
863863
}
864-
864+
865865
});
866866
displayDiffView();
867867
}
@@ -891,7 +891,7 @@ private Map.Entry<File, File[]> getSelectedActionRoots () {
891891
ctx = GitUtils.getContextForFiles(filterExcluded(selectedFiles));
892892
return GitUtils.getActionRoots(ctx);
893893
}
894-
894+
895895
private File[] filterExcluded (File[] files) {
896896
List<File> filtered = new ArrayList<>(files.length);
897897
for (File f : files) {
@@ -903,7 +903,7 @@ private File[] filterExcluded (File[] files) {
903903
}
904904
return filtered.toArray(new File[0]);
905905
}
906-
906+
907907
private boolean showingFileComponent() {
908908
return getActiveFileComponent() != null;
909909
}
@@ -1064,7 +1064,7 @@ private DiffMode getDiffMode () {
10641064
}
10651065
return diffMode;
10661066
}
1067-
1067+
10681068
private Revision getSelectedRevision (JComboBox cmbDiffTree) {
10691069
Object selectedItem = cmbDiffTree.getSelectedItem();
10701070
Revision selection = null;
@@ -1123,15 +1123,25 @@ public void propertyChange (PropertyChangeEvent evt) {
11231123
if (FileStatusCache.PROP_FILE_STATUS_CHANGED.equals(evt.getPropertyName())) {
11241124
FileStatusCache.ChangedEvent changedEvent = (FileStatusCache.ChangedEvent) evt.getNewValue();
11251125
if (LOG.isLoggable(Level.FINE)) {
1126-
LOG.log(Level.FINE, "File status for file {0} changed from {1} to {2}", new Object[] {
1127-
changedEvent.getFile(),
1126+
LOG.log(Level.FINE, "File status for file {0} changed from {1} to {2}", new Object[] {
1127+
changedEvent.getFile(),
11281128
changedEvent.getOldInfo(),
11291129
changedEvent.getNewInfo() } );
11301130
}
1131-
if (revisionLeft == Revision.HEAD // remove when we're able to refresh single file changes for Local vs. any revision
1131+
if (revisionLeft == Revision.HEAD // remove when we're able to refresh single file changes for Local vs. any revision
11321132
&& revisionRight == Revision.LOCAL && affectsView(changedEvent)) {
11331133
applyChange(changedEvent);
11341134
}
1135+
} else if (FileStatusCache.PROP_FILES_STATUS_CHANGED.equals(evt.getPropertyName())) {
1136+
if (revisionLeft == Revision.HEAD && revisionRight == Revision.LOCAL) {
1137+
@SuppressWarnings("unchecked")
1138+
List<FileStatusCache.ChangedEvent> changedEvents = (List<FileStatusCache.ChangedEvent>) evt.getNewValue();
1139+
for (FileStatusCache.ChangedEvent changedEvent : changedEvents) {
1140+
if (affectsView(changedEvent)) {
1141+
applyChange(changedEvent);
1142+
}
1143+
}
1144+
}
11351145
} else if (DiffController.PROP_DIFFERENCES.equals(evt.getPropertyName())) {
11361146
// something has changed
11371147
Setup setup = currentSetup;
@@ -1537,7 +1547,7 @@ private boolean isLocal () {
15371547
* Eliminates unnecessary cache.listFiles call as well as the whole node creation process ()
15381548
*/
15391549
private final class ApplyChangesTask implements Runnable, Cancellable {
1540-
1550+
15411551
private volatile boolean canceled;
15421552

15431553
@Override
@@ -1651,7 +1661,7 @@ public boolean cancel () {
16511661
return true;
16521662
}
16531663
}
1654-
1664+
16551665
private class RefreshComboTask implements Runnable {
16561666

16571667
@Override
@@ -1663,7 +1673,7 @@ public void run () {
16631673
if (revisionOriginalLeft != Revision.HEAD) {
16641674
modelLeft.add(Revision.HEAD);
16651675
}
1666-
modelRight.add(revisionOriginalRight);
1676+
modelRight.add(revisionOriginalRight);
16671677
if (revisionOriginalRight != Revision.LOCAL) {
16681678
modelRight.add(Revision.LOCAL);
16691679
}
@@ -1767,7 +1777,7 @@ public void run() {
17671777
GitClientExceptionHandler.notifyException(exception, true);
17681778
}
17691779
}
1770-
1780+
17711781
private DiffNode[] prepareSetupsToRefresh () {
17721782
return Mutex.EVENT.readAccess(new Mutex.Action<DiffNode[]>() {
17731783
@Override
@@ -1810,7 +1820,7 @@ private int getMatchingLine (StreamSource ss2, StreamSource ss1, int requestedRi
18101820
}
18111821
}
18121822
}// </editor-fold>
1813-
1823+
18141824
@NbBundle.Messages({
18151825
"MSG_Revision_Select_Tooltip=Select a revision from the picker"
18161826
})

ide/git/src/org/netbeans/modules/git/ui/status/VersioningPanelController.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,14 @@ public void propertyChange (PropertyChangeEvent evt) {
408408
if (affectsView((FileStatusCache.ChangedEvent) evt.getNewValue())) {
409409
applyChange(changedEvent);
410410
}
411+
} else if (FileStatusCache.PROP_FILES_STATUS_CHANGED.equals(evt.getPropertyName())) {
412+
@SuppressWarnings("unchecked")
413+
List<FileStatusCache.ChangedEvent> changedEvents = (List<FileStatusCache.ChangedEvent>) evt.getNewValue();
414+
for (FileStatusCache.ChangedEvent changedEvent : changedEvents) {
415+
if (affectsView(changedEvent)) {
416+
applyChange(changedEvent);
417+
}
418+
}
411419
}
412420
}
413421

0 commit comments

Comments
 (0)