Skip to content

Commit 8d4384d

Browse files
#213 Fix rider slowness issues on loading of insights list
1 parent b9e14d4 commit 8d4384d

File tree

11 files changed

+110
-70
lines changed

11 files changed

+110
-70
lines changed

ide-common/src/main/java/org/digma/intellij/plugin/document/DocumentInfoContainer.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ public void update(@NotNull DocumentInfo documentInfo) {
6767
loadAllInsightsForCurrentDocument();
6868
}
6969

70-
public void refresh() {
70+
public void updateCache() {
7171
Log.log(LOGGER::debug, "Refreshing document backend data for {}: ", psiFile.getVirtualFile());
7272
loadAllInsightsForCurrentDocument();
7373
}

ide-common/src/main/java/org/digma/intellij/plugin/document/DocumentInfoService.java

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import org.digma.intellij.plugin.model.discovery.MethodInfo;
1212
import org.digma.intellij.plugin.model.discovery.MethodUnderCaret;
1313
import org.digma.intellij.plugin.model.rest.insights.CodeObjectInsight;
14+
import org.digma.intellij.plugin.model.rest.usage.UsageStatusResult;
1415
import org.digma.intellij.plugin.psi.PsiUtils;
1516
import org.jetbrains.annotations.NotNull;
1617
import org.jetbrains.annotations.Nullable;
@@ -71,18 +72,24 @@ public void environmentChanged(String newEnv) {
7172

7273
//refresh all backend data.
7374
//must run in background
74-
refreshAll();
75+
updateCacheForAllOpenedDocuments();
7576
}
7677

7778

78-
public void refreshAll(){
79-
documents.forEach((psiFileUri, container) -> container.refresh());
79+
public void updateCacheForAllOpenedDocuments(){
80+
documents.forEach((psiFileUri, container) -> container.updateCache());
81+
}
82+
83+
public void updateCacheForOtherOpenedDocuments(String selectedDocumentFileUri){
84+
Map<String, DocumentInfoContainer> documentsToRefresh = new HashMap<>(documents);
85+
documentsToRefresh.remove(selectedDocumentFileUri);
86+
documentsToRefresh.forEach((psiFileUri, container) -> container.updateCache());
8087
}
8188

8289
public void refreshIfExists(PsiFile psiFile) {
8390
DocumentInfoContainer documentInfoContainer = documents.get(PsiUtils.psiFileToUri(psiFile));
8491
if (documentInfoContainer != null) {
85-
documentInfoContainer.refresh();
92+
documentInfoContainer.updateCache();
8693
}
8794
}
8895

@@ -109,7 +116,17 @@ public void removeDocumentInfo(@NotNull PsiFile psiFile) {
109116
documents.remove(PsiUtils.psiFileToUri(psiFile));
110117
}
111118

112-
@NotNull
119+
public UsageStatusResult getCachedUsageStatus(@NotNull MethodInfo methodInfo, List<String> objectIds) {
120+
Log.log(LOGGER::debug, "Requesting cached usage status for MethodInfo {} and for objectIds {} ", methodInfo.getId(), objectIds);
121+
122+
DocumentInfoContainer documentInfoContainer = documents.get(methodInfo.getContainingFileUri());
123+
if (documentInfoContainer == null) {
124+
Log.log(LOGGER::debug, "DocumentInfoContainer is null ");
125+
return new UsageStatusResult(Collections.emptyList(), Collections.emptyList());
126+
}
127+
return documentInfoContainer.getUsageStatus();
128+
}
129+
113130
public List<CodeObjectInsight> getCachedMethodInsights(@NotNull MethodInfo methodInfo) {
114131
Log.log(LOGGER::debug, "Requesting cached insights for MethodInfo {}", methodInfo.getId());
115132

@@ -126,6 +143,10 @@ public List<CodeObjectInsight> getCachedMethodInsights(@NotNull MethodInfo metho
126143
return new ArrayList<>();
127144
}
128145

146+
public DocumentInfoContainer getDocumentInfoByMethodInfo(@NotNull MethodInfo methodInfo) {
147+
return documents.get(methodInfo.getContainingFileUri());
148+
}
149+
129150
@Nullable
130151
public DocumentInfoContainer getDocumentInfo(PsiFile psiFile) {
131152
return documents.get(PsiUtils.psiFileToUri(psiFile));

ide-common/src/main/java/org/digma/intellij/plugin/insights/InsightsProvider.java

Lines changed: 1 addition & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
import com.intellij.openapi.project.Project;
55
import org.apache.commons.lang3.time.StopWatch;
66
import org.digma.intellij.plugin.analytics.AnalyticsService;
7-
import org.digma.intellij.plugin.analytics.AnalyticsServiceException;
87
import org.digma.intellij.plugin.document.DocumentInfoService;
98
import org.digma.intellij.plugin.insights.view.BuildersHolder;
109
import org.digma.intellij.plugin.insights.view.InsightsViewBuilder;
@@ -36,22 +35,6 @@ public InsightsProvider(Project project) {
3635
this.project = project;
3736
}
3837

39-
public InsightsListContainer getUpdatedInsightsList(@NotNull MethodInfo methodInfo) {
40-
List<? extends CodeObjectInsight> upToDateInsightsList;
41-
List<String> objectIds = getObjectIds(methodInfo);
42-
Log.log(LOGGER::debug, "Got following code object ids for method {}: {}", methodInfo.getId(), objectIds);
43-
var stopWatch = StopWatch.createStarted();
44-
try {
45-
//refresh insights cache
46-
documentInfoService.refreshAll();
47-
upToDateInsightsList = documentInfoService.getCachedMethodInsights(methodInfo);
48-
} finally {
49-
stopWatch.stop();
50-
Log.log(LOGGER::debug, "getInsights time took {} milliseconds", stopWatch.getTime(TimeUnit.MILLISECONDS));
51-
}
52-
return getInsightsListContainer(methodInfo, upToDateInsightsList);
53-
}
54-
5538
public InsightsListContainer getCachedInsights(@NotNull MethodInfo methodInfo) {
5639
List<? extends CodeObjectInsight> cachedMethodInsights = documentInfoService.getCachedMethodInsights(methodInfo);
5740
return getInsightsListContainer(methodInfo, cachedMethodInsights);
@@ -66,18 +49,11 @@ public InsightsListContainer getInsightsListContainer(@NotNull MethodInfo method
6649
List<? extends CodeObjectInsight> codeObjectInsights = insightsList;
6750
codeObjectInsights = filterUnmapped(codeObjectInsights);
6851
Log.log(LOGGER::debug, "CodeObjectInsights for {}: {}", methodInfo.getId(), codeObjectInsights);
69-
final UsageStatusResult usageStatus = analyticsService.getUsageStatus(objectIds);
52+
final UsageStatusResult usageStatus = documentInfoService.getCachedUsageStatus(methodInfo, objectIds);
7053
InsightsViewBuilder insightsViewBuilder = new InsightsViewBuilder(buildersHolder);
7154
List<ListViewItem<?>> listViewItems = insightsViewBuilder.build(project,methodInfo, codeObjectInsights);
7255
Log.log(LOGGER::debug, "ListViewItems for {}: {}", methodInfo.getId(), listViewItems);
7356
return new InsightsListContainer(listViewItems, codeObjectInsights.size(), usageStatus);
74-
} catch (AnalyticsServiceException e) {
75-
//if analyticsService.getUsageStatus throws exception it means usageStatus could not be loaded, usually when
76-
//the backend is not available. return an empty InsightsListContainer to keep everything running and don't
77-
//crash the plugin. don't log the exception, it was logged in AnalyticsService, keep the log quite because
78-
//it may happen many times.
79-
Log.log(LOGGER::debug, "AnalyticsServiceException for getUsageStatus for {}: {}", methodInfo.getId(), e.getMessage());
80-
return new InsightsListContainer();
8157
} finally {
8258
stopWatch.stop();
8359
Log.log(LOGGER::debug, "getUsageStatus time took {} milliseconds", stopWatch.getTime(TimeUnit.MILLISECONDS));

ide-common/src/main/kotlin/org/digma/intellij/plugin/ui/service/ErrorsViewService.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ class ErrorsViewService(project: Project) : AbstractViewService(project) {
4141
return "Errors" + if (model.errorsCount > 0) " (${model.count()})" else ""
4242
}
4343

44-
fun contextChanged(
44+
fun updateErrorsModel(
4545
methodInfo: MethodInfo
4646
) {
4747
lock.lock()
@@ -171,11 +171,11 @@ class ErrorsViewService(project: Project) : AbstractViewService(project) {
171171
return emptyErrorDetails
172172
}
173173

174-
fun refreshErrors() {
174+
fun refreshErrorsModel() {
175175
val scope = model.scope
176176
if (scope is MethodScope) {
177-
Backgroundable.ensureBackground(project, "Refresh errors list") {
178-
contextChanged(scope.getMethodInfo())
177+
Backgroundable.ensureBackground(project, "Refresh errors model") {
178+
updateErrorsModel(scope.getMethodInfo())
179179
}
180180
}
181181
}

ide-common/src/main/kotlin/org/digma/intellij/plugin/ui/service/InsightsViewService.kt

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
package org.digma.intellij.plugin.ui.service
22

33
import com.intellij.openapi.diagnostic.Logger
4+
import com.intellij.openapi.fileEditor.FileEditorManager
45
import com.intellij.openapi.project.Project
56
import org.digma.intellij.plugin.common.Backgroundable
67
import org.digma.intellij.plugin.document.DocumentInfoContainer
8+
import org.digma.intellij.plugin.document.DocumentInfoService
79
import org.digma.intellij.plugin.insights.InsightsListContainer
810
import org.digma.intellij.plugin.insights.InsightsProvider
911
import org.digma.intellij.plugin.log.Log
@@ -43,21 +45,16 @@ class InsightsViewService(project: Project) : AbstractViewService(project) {
4345
}
4446
}
4547

46-
fun contextChanged(
48+
fun updateInsightsModel(
4749
methodInfo: MethodInfo
48-
) {
49-
updateInsightsModel(methodInfo, insightsProvider.getCachedInsights(methodInfo))
50-
}
51-
52-
private fun updateInsightsModel(
53-
methodInfo: MethodInfo,
54-
insightsListContainer: InsightsListContainer
5550
) {
5651
lock.lock()
5752
Log.log(logger::debug, "Lock acquired for updateInsightsModel to {}. ", methodInfo)
5853
try {
5954
Log.log(logger::debug, "updateInsightsModel to {}. ", methodInfo)
6055

56+
val insightsListContainer = insightsProvider.getCachedInsights(methodInfo)
57+
6158
model.listViewItems = insightsListContainer.listViewItems
6259
model.previewListViewItems = ArrayList()
6360
model.usageStatusResult = insightsListContainer.usageStatus
@@ -169,11 +166,11 @@ class InsightsViewService(project: Project) : AbstractViewService(project) {
169166

170167
}
171168

172-
fun refreshAllInsights() {
169+
fun refreshInsightsModel() {
173170
val scope = model.scope
174171
if (scope is MethodScope) {
175-
Backgroundable.ensureBackground(project, "Refresh insights list") {
176-
updateInsightsModel(scope.getMethodInfo(), insightsProvider.getUpdatedInsightsList(scope.getMethodInfo()))
172+
Backgroundable.ensureBackground(project, "Refresh insights model") {
173+
updateInsightsModel(scope.getMethodInfo())
177174
}
178175
}
179176
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package org.digma.intellij.plugin.ui.service
2+
3+
import com.intellij.openapi.fileEditor.FileEditorManager
4+
import com.intellij.openapi.project.Project
5+
import org.digma.intellij.plugin.common.Backgroundable
6+
import org.digma.intellij.plugin.document.DocumentInfoService
7+
import org.digma.intellij.plugin.ui.model.MethodScope
8+
9+
class RefreshService(private val project: Project) {
10+
11+
private val errorsViewService: ErrorsViewService = project.getService(ErrorsViewService::class.java)
12+
private val insightsViewService: InsightsViewService = project.getService(InsightsViewService::class.java)
13+
14+
companion object {
15+
fun getInstance(project: Project): RefreshService {
16+
return project.getService(RefreshService::class.java)
17+
}
18+
}
19+
20+
fun refreshAll() {
21+
val scope = insightsViewService.model.scope
22+
val selectedTextEditor = FileEditorManager.getInstance(project).selectedTextEditor
23+
if (scope is MethodScope) {
24+
val documentInfoContainer = DocumentInfoService.getInstance(project).getDocumentInfoByMethodInfo(scope.getMethodInfo())
25+
26+
Backgroundable.ensureBackground(project, "Refresh insights and errors list") {
27+
val selectedDocument = selectedTextEditor?.document
28+
29+
if (selectedDocument != null) {
30+
documentInfoContainer?.updateCache()
31+
}
32+
insightsViewService.updateInsightsModel(scope.getMethodInfo())
33+
errorsViewService.updateErrorsModel(scope.getMethodInfo())
34+
35+
// update all our local cache in the background
36+
if (selectedDocument != null) {
37+
DocumentInfoService.getInstance(project).updateCacheForOtherOpenedDocuments(documentInfoContainer?.documentInfo?.fileUri)
38+
} else {
39+
DocumentInfoService.getInstance(project).updateCacheForAllOpenedDocuments()
40+
}
41+
}
42+
}
43+
}
44+
}

java/src/main/java/org/digma/intellij/plugin/idea/psi/java/JavaSpanNavigationProvider.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,8 @@ public void buildSpanNavigation() {
8888
//for example is the IDE is closed when the cursor is on a method with Duration Breakdown that
8989
// has span links, then start the IDE again, the insights view is populted already, without this refresh
9090
// there will be no links.
91-
project.getService(InsightsViewService.class).refreshAllInsights();
92-
project.getService(ErrorsViewService.class).refreshErrors();
91+
project.getService(InsightsViewService.class).refreshInsightsModel();
92+
project.getService(ErrorsViewService.class).refreshErrorsModel();
9393

9494
} finally {
9595
buildSpansLock.unlock();

src/main/java/org/digma/intellij/plugin/service/EditorInteractionService.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -188,8 +188,8 @@ private void contextChangedImpl(MethodUnderCaret methodUnderCaret) {
188188
errorsViewService.contextChangeNoMethodInfo(dummyMethodInfo);
189189
} else {
190190
Log.log(LOGGER::debug, "Context changed to {}. ", methodInfo);
191-
insightsViewService.contextChanged(methodInfo);
192-
errorsViewService.contextChanged(methodInfo);
191+
insightsViewService.updateInsightsModel(methodInfo);
192+
errorsViewService.updateErrorsModel(methodInfo);
193193
}
194194

195195
}

src/main/kotlin/org/digma/intellij/plugin/ui/common/Panels.kt

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,10 @@ import org.digma.intellij.plugin.ui.model.errors.ErrorsModel
1717
import org.digma.intellij.plugin.ui.model.insights.InsightsModel
1818
import org.digma.intellij.plugin.ui.panels.DigmaResettablePanel
1919
import org.digma.intellij.plugin.ui.panels.DigmaTabPanel
20-
import org.digma.intellij.plugin.ui.service.ErrorsViewService
21-
import org.digma.intellij.plugin.ui.service.InsightsViewService
20+
import org.digma.intellij.plugin.ui.service.RefreshService
2221
import java.awt.BorderLayout
2322
import java.awt.Cursor
2423
import java.awt.Dimension
25-
import java.awt.event.MouseAdapter
26-
import java.awt.event.MouseEvent
2724
import javax.swing.*
2825

2926

@@ -105,8 +102,7 @@ fun wrapWithNoConnectionWrapper(project: Project, panel: DigmaTabPanel): DigmaTa
105102
}
106103

107104
private fun getGeneralRefreshButton(project: Project): JButton {
108-
val insightsActionListener: InsightsViewService = project.getService(InsightsViewService::class.java)
109-
val errorsActionListener: ErrorsViewService = project.getService(ErrorsViewService::class.java)
105+
val refreshService: RefreshService = project.getService(RefreshService::class.java)
110106

111107
val size = Laf.scalePanels(Laf.Sizes.BUTTON_SIZE_26)
112108
val buttonsSize = Dimension(size, size)
@@ -116,12 +112,9 @@ private fun getGeneralRefreshButton(project: Project): JButton {
116112
generalRefreshIconButton.toolTipText = asHtml(REFRESH_ALL_INSIGHTS_AND_ERRORS)
117113
generalRefreshIconButton.cursor = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)
118114

119-
generalRefreshIconButton.addMouseListener(object : MouseAdapter() {
120-
override fun mouseClicked(e: MouseEvent?) {
121-
insightsActionListener.refreshAllInsights()
122-
errorsActionListener.refreshErrors()
123-
}
124-
})
115+
generalRefreshIconButton.addActionListener {
116+
refreshService.refreshAll()
117+
}
125118
return generalRefreshIconButton
126119
}
127120

src/main/kotlin/org/digma/intellij/plugin/ui/list/insights/InsightsCommon.kt

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,22 @@ import io.ktor.util.reflect.*
1010
import org.digma.intellij.plugin.analytics.AnalyticsService
1111
import org.digma.intellij.plugin.model.InsightType
1212
import org.digma.intellij.plugin.model.rest.insights.CodeObjectInsight
13-
import org.digma.intellij.plugin.ui.common.*
13+
import org.digma.intellij.plugin.ui.common.Laf
14+
import org.digma.intellij.plugin.ui.common.asHtml
15+
import org.digma.intellij.plugin.ui.common.buildBoldTitleGrayedComment
1416
import org.digma.intellij.plugin.ui.list.PanelsLayoutHelper
1517
import org.digma.intellij.plugin.ui.list.commonListItemPanel
1618
import org.digma.intellij.plugin.ui.panels.DigmaResettablePanel
17-
import org.digma.intellij.plugin.ui.service.InsightsViewService
18-
import java.awt.*
19+
import org.digma.intellij.plugin.ui.service.RefreshService
20+
import java.awt.BorderLayout
21+
import java.awt.Cursor
22+
import java.awt.Dimension
23+
import java.awt.FlowLayout
1924
import java.awt.event.MouseAdapter
2025
import java.awt.event.MouseEvent
21-
import java.time.*
26+
import java.time.Duration
27+
import java.time.LocalDateTime
28+
import java.time.ZoneId
2229
import java.util.*
2330
import javax.swing.*
2431
import kotlin.math.max
@@ -198,7 +205,7 @@ private fun getTimeInfoMessagePanel(
198205
timeInfoMessageLabelPanel.isOpaque = false
199206
timeInfoMessageLabelPanel.add(timeInfoMessageLabel)
200207
if (shouldShowApplyNewTimeFilterLabel(isRecalculateButtonPressed, identicalStartTimes)) {
201-
timeInfoMessageLabelPanel.add(getRefreshButton(insightPanel, project))
208+
timeInfoMessageLabelPanel.add(getRefreshInsightButton(insightPanel, project))
202209
}
203210
return timeInfoMessageLabelPanel
204211
}
@@ -317,11 +324,11 @@ private fun showHintMessage(
317324
HintManager.getInstance().showHint(recalculateAction, RelativePoint.getSouthWestOf(threeDotsIcon), HintManager.HIDE_BY_ESCAPE, 2000)
318325
}
319326

320-
private fun getRefreshButton(insightPanel: DigmaResettablePanel, project: Project): ActionLink {
327+
private fun getRefreshInsightButton(insightPanel: DigmaResettablePanel, project: Project): ActionLink {
321328
val refreshAction = ActionLink(REFRESH)
322329
refreshAction.addActionListener {
323-
val actionListener: InsightsViewService = project.getService(InsightsViewService::class.java)
324-
actionListener.refreshAllInsights()
330+
val refreshService: RefreshService = project.getService(RefreshService::class.java)
331+
refreshService.refreshAll()
325332
rebuildInsightPanel(insightPanel)
326333
}
327334
refreshAction.border = empty()

0 commit comments

Comments
 (0)