eclipse-jdt / eclipse-jdt/eclipse.jdt.debug
Long UI freezes during debugging
- Dominant language
- Java
- Stars
- 23
- Forks
- 68
- Avg merge
- 1d 4h
- Merged PRs (30d)
- 13
Description
Debugging remote services could lead to long freezes in the UI. The UI freeze monitor showed me a couple of traces like these:
```
at java.base@17.0.4/java.lang.Object.wait(Native Method)
at org.eclipse.jdi.internal.connect.PacketReceiveManager.waitForPacketAvailable(PacketReceiveManager.java:220)
at org.eclipse.jdi.internal.connect.PacketReceiveManager.getReply(PacketReceiveManager.java:165)
at org.eclipse.jdi.internal.connect.PacketReceiveManager.getReply(PacketReceiveManager.java:207)
at org.eclipse.jdi.internal.MirrorImpl.requestVM(MirrorImpl.java:195)
at org.eclipse.jdi.internal.MirrorImpl.requestVM(MirrorImpl.java:230)
at org.eclipse.jdi.internal.ArrayReferenceImpl.getValues(ArrayReferenceImpl.java:127)
at org.eclipse.jdi.internal.ArrayReferenceImpl.getValue(ArrayReferenceImpl.java:76)
at org.eclipse.jdt.internal.debug.core.model.JDIArrayEntryVariable.retrieveValue(JDIArrayEntryVariable.java:91)
at org.eclipse.jdt.internal.debug.core.model.JDIVariable.getCurrentValue(JDIVariable.java:74)
at org.eclipse.jdt.internal.debug.core.model.JDIVariable.getValue(JDIVariable.java:98)
at org.eclipse.jdt.internal.debug.core.model.JDIArrayEntryVariable.equals(JDIArrayEntryVariable.java:257)
at org.eclipse.jface.viewers.CustomHashtable.keyEquals(CustomHashtable.java:280)
at org.eclipse.jface.viewers.CustomHashtable.get(CustomHashtable.java:245)
at org.eclipse.jface.viewers.StructuredViewer.findItems(StructuredViewer.java:752)
at org.eclipse.debug.internal.ui.viewers.model.InternalTreeModelViewer.findItem(InternalTreeModelViewer.java:1119)
at org.eclipse.debug.internal.ui.viewers.model.InternalTreeModelViewer.setElementData(InternalTreeModelViewer.java:1385)
at org.eclipse.debug.internal.ui.viewers.model.TreeModelLabelProvider.setElementData(TreeModelLabelProvider.java:325)
at org.eclipse.debug.internal.ui.viewers.model.LabelUpdate.performUpdate(LabelUpdate.java:140)
at org.eclipse.debug.internal.ui.viewers.model.TreeModelLabelProvider.lambda$0(TreeModelLabelProvider.java:412)
at org.eclipse.debug.internal.ui.viewers.model.TreeModelLabelProvider$$Lambda$1718/0x0000000801e73268.run(Unknown Source)
at org.eclipse.swt.widgets.RunnableLock.run(RunnableLock.java:40)
```
and
```
at org.eclipse.jdi.internal.MirrorImpl.(MirrorImpl.java:84)
at org.eclipse.jdi.internal.ValueImpl.(ValueImpl.java:49)
at org.eclipse.jdi.internal.ObjectReferenceImpl.(ObjectReferenceImpl.java:76)
at org.eclipse.jdi.internal.ObjectReferenceImpl.(ObjectReferenceImpl.java:68)
at org.eclipse.jdi.internal.ObjectReferenceImpl.readObjectRefWithoutTag(ObjectReferenceImpl.java:638)
at org.eclipse.jdi.internal.ObjectReferenceImpl.readObjectRefWithTag(ObjectReferenceImpl.java:652)
at org.eclipse.jdi.internal.ArrayReferenceImpl.readObjectSequence(ArrayReferenceImpl.java:198)
at org.eclipse.jdi.internal.ArrayReferenceImpl.getValues(ArrayReferenceImpl.java:157)
at org.eclipse.jdi.internal.ArrayReferenceImpl.getValue(ArrayReferenceImpl.java:76)
at org.eclipse.jdt.internal.debug.core.model.JDIArrayEntryVariable.retrieveValue(JDIArrayEntryVariable.java:91)
at org.eclipse.jdt.internal.debug.core.model.JDIVariable.getCurrentValue(JDIVariable.java:74)
at org.eclipse.jdt.internal.debug.core.model.JDIVariable.getValue(JDIVariable.java:98)
at org.eclipse.jdt.internal.debug.core.model.JDIArrayEntryVariable.equals(JDIArrayEntryVariable.java:257)
at org.eclipse.debug.internal.ui.viewers.model.ViewerStateTracker.lambda$8(ViewerStateTracker.java:984)
at org.eclipse.debug.internal.ui.viewers.model.ViewerStateTracker$$Lambda$1728/0x0000000801eaa458.visit(Unknown Source)
at org.eclipse.debug.internal.ui.viewers.model.provisional.ModelDelta.doAccept(ModelDelta.java:376)
at org.eclipse.debug.internal.ui.viewers.model.provisional.ModelDelta.doAccept(ModelDelta.java:378)
at org.eclipse.debug.internal.ui.viewers.model.provisional.ModelDelta.doAccept(ModelDelta.java:378)
at org.eclipse.debug.internal.ui.viewers.model.provisional.ModelDelta.doAccept(ModelDelta.java:378)
at org.eclipse.debug.internal.ui.viewers.model.provisional.ModelDelta.accept(ModelDelta.java:372)
at org.eclipse.debug.internal.ui.viewers.model.ViewerStateTracker.restorePendingStateOnUpdate(ViewerStateTracker.java:999)
at org.eclipse.debug.internal.ui.viewers.model.ChildrenUpdate.performUpdate(ChildrenUpdate.java:95)
at org.eclipse.debug.internal.ui.viewers.model.ChildrenUpdate.performUpdate(ChildrenUpdate.java:112)
at org.eclipse.debug.internal.ui.viewers.model.TreeModelContentProvider.performUpdates(TreeModelContentProvider.java:1830)
at org.eclipse.debug.internal.ui.viewers.model.TreeModelContentProvider.lambda$2(TreeModelContentProvider.java:1793)
at org.eclipse.debug.internal.ui.viewers.model.TreeModelContentProvider$$Lambda$1002/0x00000008015edc18.run(Unknown Source)
at org.eclipse.debug.internal.ui.viewers.model.TreeModelContentProvider$DelayedDoModelChangedJob.runInUIThread(TreeModelContentProvider.java:452)
```
and
```
at org.eclipse.jdi.internal.connect.PacketReceiveManager.waitForPacketAvailable(PacketReceiveManager.java:220)
at org.eclipse.jdi.internal.connect.PacketReceiveManager.getReply(PacketReceiveManager.java:165)
at org.eclipse.jdi.internal.connect.PacketReceiveManager.getReply(PacketReceiveManager.java:207)
at org.eclipse.jdi.internal.MirrorImpl.requestVM(MirrorImpl.java:195)
at org.eclipse.jdi.internal.MirrorImpl.requestVM(MirrorImpl.java:230)
at org.eclipse.jdi.internal.ArrayReferenceImpl.getValues(ArrayReferenceImpl.java:127)
at org.eclipse.jdi.internal.ArrayReferenceImpl.getValue(ArrayReferenceImpl.java:76)
at org.eclipse.jdt.internal.debug.core.model.JDIArrayEntryVariable.retrieveValue(JDIArrayEntryVariable.java:91)
at org.eclipse.jdt.internal.debug.core.model.JDIVariable.getCurrentValue(JDIVariable.java:74)
at org.eclipse.jdt.internal.debug.core.model.JDIVariable.getValue(JDIVariable.java:98)
at org.eclipse.jdt.internal.debug.core.model.JDIArrayEntryVariable.equals(JDIArrayEntryVariable.java:257)
at org.eclipse.jface.viewers.TreePath.equals(TreePath.java:158)
at org.eclipse.jface.viewers.TreePath.equals(TreePath.java:106)
at org.eclipse.debug.internal.ui.viewers.model.ViewerStateTracker$CompareRequestKey.equals(ViewerStateTracker.java:199)
at java.base@17.0.4/java.util.HashMap.removeNode(HashMap.java:818)
at java.base@17.0.4/java.util.HashMap.remove(HashMap.java:797)
at org.eclipse.debug.internal.ui.viewers.model.ViewerStateTracker.compareFinished(ViewerStateTracker.java:1412)
at org.eclipse.debug.internal.ui.viewers.model.ElementCompareRequest.lambda$0(ElementCompareRequest.java:82)
at org.eclipse.debug.internal.ui.viewers.model.ElementCompareRequest$$Lambda$2004/0x0000000802040b90.run(Unknown Source)
```
and
```
at org.eclipse.jdi.internal.connect.PacketReceiveManager.waitForPacketAvailable(PacketReceiveManager.java:220)
at org.eclipse.jdi.internal.connect.PacketReceiveManager.getReply(PacketReceiveManager.java:165)
at org.eclipse.jdi.internal.connect.PacketReceiveManager.getReply(PacketReceiveManager.java:207)
at org.eclipse.jdi.internal.MirrorImpl.requestVM(MirrorImpl.java:195)
at org.eclipse.jdi.internal.MirrorImpl.requestVM(MirrorImpl.java:230)
at org.eclipse.jdi.internal.StackFrameImpl.getValues(StackFrameImpl.java:140)
at org.eclipse.jdi.internal.StackFrameImpl.getValue(StackFrameImpl.java:78)
at org.eclipse.jdt.internal.debug.core.model.JDILocalVariable.retrieveValue(JDILocalVariable.java:64)
at org.eclipse.jdt.internal.debug.core.model.JDIVariable.getCurrentValue(JDIVariable.java:74)
at org.eclipse.jdt.internal.debug.core.model.JDIVariable.getValue(JDIVariable.java:98)
at org.eclipse.jdt.internal.debug.ui.JavaVarActionFilter.testAttribute(JavaVarActionFilter.java:171)
at org.eclipse.ui.internal.ActionExpression$ObjectStateExpression.preciselyMatches(ActionExpression.java:486)
at org.eclipse.ui.internal.ActionExpression$ObjectStateExpression.isEnabledFor(ActionExpression.java:455)
at org.eclipse.ui.internal.ActionExpression$OrExpression.isEnabledFor(ActionExpression.java:531)
at org.eclipse.ui.internal.ActionExpression$AndExpression.isEnabledFor(ActionExpression.java:126)
at org.eclipse.ui.internal.ActionExpression$SingleExpression.isEnabledFor(ActionExpression.java:678)
at org.eclipse.ui.internal.ActionExpression.isEnabledFor(ActionExpression.java:970)
at org.eclipse.ui.internal.ObjectActionContributor$ObjectContribution.isApplicableTo(ObjectActionContributor.java:337)
at org.eclipse.ui.internal.ObjectActionContributor.isApplicableTo(ObjectActionContributor.java:226)
at org.eclipse.ui.internal.ObjectContributorManager.isApplicableTo(ObjectContributorManager.java:302)
at org.eclipse.ui.internal.ObjectActionContributorManager.contributeObjectActions(ObjectActionContributorManager.java:89)
```
and so on ...
Even though, for remote debugging some sort of a slowness/slugishness is certainly expected, freezing the UI for multiple seconds is a very bad experience.
The stack traces are showing a very unfortunate situation, that the code actually tries to request things over the wire in the UI thread.
Most of the stack traces are related to JDIArrayEntryVariable.equals(...) method, but there are other codepaths as well.
What do you think, how can this be solved? Probably moving those evaluations in a separate background thread would be huge, invasive change, but some sort of caching of the requests could improve things - and even make the implementation less error prone, because I'm certain, that CustomHashtable is not well prepared to properly handle constantly changing keys. But the exact details, how and until when things can be cached, would be a challenge.
Contributor guide
Assessment
This issue has not been assessed yet.