Summary: | [OS X] frequent "beachballing" | ||
---|---|---|---|
Product: | [Applications] kdevelop | Reporter: | RJVB <rjvbertin> |
Component: | Language Support: CPP (old) | Assignee: | kdevelop-bugs-null |
Status: | RESOLVED DUPLICATE | ||
Severity: | normal | CC: | kfunk |
Priority: | NOR | ||
Version First Reported In: | git master | ||
Target Milestone: | 5.0.3 | ||
Platform: | Compiled Sources | ||
OS: | macOS | ||
Latest Commit: | Version Fixed In: | ||
Sentry Crash Report: | |||
Attachments: | simple patch to prevent beachballing |
Description
RJVB
2016-04-21 13:16:24 UTC
This backtrace snippet has line numbers: frame #7: 0x000000010353a03c QtCore`QDir::entryList(this=<unavailable>, nameFilters=<unavailable>, filters=<unavailable>, sort=<unavailable>) const + 396 at qdir.cpp:1327 frame #8: 0x0000000118d22813 libKDevClangPrivate.25.dylib`(anonymous namespace)::scanIncludePaths(QString const&, QDir const&, int) + 419 frame #9: 0x0000000118d22d34 libKDevClangPrivate.25.dylib`(anonymous namespace)::scanIncludePaths(QString const&, QDir const&, int) + 1732 frame #10: 0x0000000118d22d34 libKDevClangPrivate.25.dylib`(anonymous namespace)::scanIncludePaths(QString const&, QDir const&, int) + 1732 frame #11: 0x0000000118d1e664 libKDevClangPrivate.25.dylib`(anonymous namespace)::fixUnknownDeclaration(KDevelop::QualifiedIdentifier const&, KDevelop::Path const&, KDevelop::DocumentRange const&) + 8980 frame #12: 0x0000000118d1c1e5 libKDevClangPrivate.25.dylib`UnknownDeclarationProblem::solutionAssistant() const + 181 frame #13: 0x0000000103dd6957 libKDevPlatformLanguage.10.dylib`KDevelop::StaticAssistantsManager::Private::checkAssistantForProblems(this=<unavailable>, top=<unavailable>) + 695 at staticassistantsmanager.cpp:296 frame #14: 0x0000000103dd6681 libKDevPlatformLanguage.10.dylib`KDevelop::StaticAssistantsManager::Private::updateReady(this=0x000000011aabe8f0, url=<unavailable>, topContext=0x000000012107a840) + 129 at staticassistantsmanager.cpp:257 Oops: frame #7: 0x0000000103539e9c QtCore`QDir::entryList(this=<unavailable>, filters=<unavailable>, sort=<unavailable>) const + 28 at qdir.cpp:1269 frame #8: 0x000000011ec8bc1d libKDevClangPrivate.25.dylib`(anonymous namespace)::scanIncludePaths(identifier=<unavailable>, dir=<unavailable>, maxDepth=<unavailable>) + 1453 at unknowndeclarationproblem.cpp:103 frame #9: 0x000000011ec8bd34 libKDevClangPrivate.25.dylib`(anonymous namespace)::scanIncludePaths(identifier=<unavailable>, dir=<unavailable>, maxDepth=<unavailable>) + 1732 at unknowndeclarationproblem.cpp:104 frame #10: 0x000000011ec8bd34 libKDevClangPrivate.25.dylib`(anonymous namespace)::scanIncludePaths(identifier=<unavailable>, dir=<unavailable>, maxDepth=<unavailable>) + 1732 at unknowndeclarationproblem.cpp:104 frame #11: 0x000000011ec87664 libKDevClangPrivate.25.dylib`(anonymous namespace)::fixUnknownDeclaration(KDevelop::QualifiedIdentifier const&, KDevelop::Path const&, KDevelop::DocumentRange const&) [inlined] (anonymous namespace)::scanIncludePaths(identifier=0x0000000119a3b8e8) + 119 at unknowndeclarationproblem.cpp:117 frame #12: 0x000000011ec875ed libKDevClangPrivate.25.dylib`(anonymous namespace)::fixUnknownDeclaration(KDevelop::QualifiedIdentifier const&, KDevelop::Path const&, KDevelop::DocumentRange const&) [inlined] (anonymous namespace)::includeFiles(file=<unavailable>, range=<unavailable>) + 5079 at unknowndeclarationproblem.cpp:416 frame #13: 0x000000011ec86216 libKDevClangPrivate.25.dylib`(anonymous namespace)::fixUnknownDeclaration(identifier=0x0000000119a3b8e8, file=<unavailable>, docrange=<unavailable>) + 3782 at unknowndeclarationproblem.cpp:452 frame #14: 0x000000011ec851e5 libKDevClangPrivate.25.dylib`UnknownDeclarationProblem::solutionAssistant(this=0x0000000119a3b8a0) const + 181 at unknowndeclarationproblem.cpp:506 frame #15: 0x0000000103dd6957 libKDevPlatformLanguage.10.dylib`KDevelop::StaticAssistantsManager::Private::checkAssistantForProblems(this=<unavailable>, top=<unavailable>) + 695 at staticassistantsmanager.cpp:296 frame #16: 0x0000000103dd6d98 libKDevPlatformLanguage.10.dylib`KDevelop::StaticAssistantsManager::Private::timeout(this=0x0000000112b8cc50) + 136 at staticassistantsmanager.cpp:316 This is still a frequent obstacle that really degrades the user experience. Having to wait up to several seconds every time your (mouse) cursor enters code that is not correct (or no longer correct, as in when you change a variable name) gets old really fast. Similar things also happen when entering new code. I've always been surprised that I noticed this only on Mac and not on Linux but maybe that's simply because my Linux desktops don't have a beachball cursor equivalent, and since they're so much slower than my Mac I do less development with them anyway. Earlier today I noticed a similar behaviour editing gitmessagehighlighter.cpp for a RR I have open. Replacing `format.setFontItalic(true)` with something else, I left it as `format.set(true)` while making a point edit elsewhere. Even hovering the mouse pointer over that undefined method blocked the UI. Reproducing the situation on a Mac I obtained the backtrace below. Apparently this particular and relatively costly parsing operation is performed on the main thread, blocking event handling (which is exactly what triggers the beachball cursor on OS X). Ideally this operation would be performed on a thread of its own, while the main thread continues to process events and aborts the operation in reaction to certain events (text input or focus movement that changes the expression being parsed, for instance). * frame #0: 0x00007fff8ca0ddfa libsystem_kernel.dylib`stat$INODE64 + 10 frame #1: 0x000000010975989f QtCore`QFileSystemEngine::fillMetaData(entry=0x00007f8549681788, data=0x00007f85496817a0, what=<unavailable>) + 271 at qfilesystemengine_unix.cpp:470 [opt] frame #2: 0x00000001096fd481 QtCore`QFileInfo::isHidden(this=<unavailable>) const + 81 at qfileinfo.cpp:967 [opt] frame #3: 0x00000001096f5413 QtCore`QDirIteratorPrivate::matchesFilters(this=0x00007f854b70ce50, fileName=<unavailable>, fi=0x00007fff59697f40) const + 387 at qdiriterator.cpp:352 [opt] frame #4: 0x00000001096f4cc5 QtCore`QDirIteratorPrivate::advance(this=0x00007f854b70ce50) + 1045 at qdiriterator.cpp:249 [opt] frame #5: 0x00000001096f5cf5 QtCore`QDirIterator::next(this=0x00007fff59698068) + 21 at qdiriterator.cpp:481 [opt] frame #6: 0x00000001096eadf3 QtCore`QDir::entryList(this=<unavailable>, nameFilters=<unavailable>, filters=<unavailable>, sort=<unavailable>) const + 499 at qdir.cpp:1325 [opt] frame #7: 0x00000001096eabec QtCore`QDir::entryList(this=<unavailable>, filters=<unavailable>, sort=<unavailable>) const + 28 at qdir.cpp:1265 [opt] frame #8: 0x000000011fc9359a libKDevClangPrivate.26.dylib`(anonymous namespace)::scanIncludePaths(identifier="set", dir=<unavailable>, maxDepth=<unavailable>) + 1722 at unknowndeclarationproblem.cpp:104 [opt] frame #9: 0x000000011fc93695 libKDevClangPrivate.26.dylib`(anonymous namespace)::scanIncludePaths(identifier="set", dir=<unavailable>, maxDepth=1) + 1973 at unknowndeclarationproblem.cpp:105 [opt] frame #10: 0x000000011fc93695 libKDevClangPrivate.26.dylib`(anonymous namespace)::scanIncludePaths(identifier="set", dir=<unavailable>, maxDepth=2) + 1973 at unknowndeclarationproblem.cpp:105 [opt] frame #11: 0x000000011fc8ee44 libKDevClangPrivate.26.dylib`(anonymous namespace)::fixUnknownDeclaration(KDevelop::QualifiedIdentifier const&, KDevelop::Path const&, KDevelop::DocumentRange const&) + 121 at unknowndeclarationproblem.cpp:118 [opt] frame #12: 0x000000011fc8edcb libKDevClangPrivate.26.dylib`(anonymous namespace)::fixUnknownDeclaration(KDevelop::QualifiedIdentifier const&, KDevelop::Path const&, KDevelop::DocumentRange const&) [inlined] (anonymous namespace)::includeFiles(declarations=<unavailable>, file=("Volumes", "Debian", "Users", "bertin", "work", "src", "new", "KDE", "KF5", "kdevplatform-git-5", "plugins", "git", "gitmessagehighlighter.cpp")) + 4271 at unknowndeclarationproblem.cpp:390 [opt] frame #13: 0x000000011fc8dd1c libKDevClangPrivate.26.dylib`(anonymous namespace)::fixUnknownDeclaration(identifier=0x00007f854f7909c8, file=("Volumes", "Debian", "Users", "bertin", "work", "src", "new", "KDE", "KF5", "kdevplatform-git-5", "plugins", "git", "gitmessagehighlighter.cpp"), docrange=<unavailable>) + 5724 at unknowndeclarationproblem.cpp:466 [opt] frame #14: 0x000000011fc8c552 libKDevClangPrivate.26.dylib`UnknownDeclarationProblem::solutionAssistant(this=0x00007f854f790980) const + 178 at unknowndeclarationproblem.cpp:520 [opt] frame #15: 0x000000011fc90c12 libKDevClangPrivate.26.dylib`non-virtual thunk to UnknownDeclarationProblem::solutionAssistant(this=<unavailable>) const + 18 at unknowndeclarationproblem.cpp:517 [opt] frame #16: 0x000000010a080cb7 libKDevPlatformLanguage.10.dylib`KDevelop::ProblemNavigationContext::html(this=<unavailable>, shorten=<unavailable>) + 6551 at problemnavigationcontext.cpp:172 [opt] frame #17: 0x000000010a082fb6 libKDevPlatformLanguage.10.dylib`KDevelop::AbstractNavigationWidget::update(this=0x00007f856316dff0) + 54 at abstractnavigationwidget.cpp:148 [opt] frame #18: 0x000000010a082e90 libKDevPlatformLanguage.10.dylib`KDevelop::AbstractNavigationWidget::setContext(this=0x00007f856316dff0, context=<unavailable>, initBrows=<unavailable>) + 224 at abstractnavigationwidget.cpp:116 [opt] frame #19: 0x000000011eb6229c kdevcontextbrowser.so`ContextBrowserPlugin::navigationWidgetForPosition(this=0x00007f855be738e0, view=0x00007f855d4cbe00, position=<unavailable>) + 2828 at contextbrowser.cpp:539 [opt] frame #20: 0x000000011eb60dfa kdevcontextbrowser.so`ContextBrowserPlugin::showToolTip(this=0x00007f855be738e0, view=0x00007f855d4cbe00, position=<unavailable>) + 90 at contextbrowser.cpp:585 [opt] frame #21: 0x000000011eb60d84 kdevcontextbrowser.so`ContextBrowserHintProvider::textHint(this=0x00007f855be73a58, view=<unavailable>, cursor=(39, 12)) + 324 at contextbrowser.cpp:407 [opt] frame #22: 0x0000000107282297 libKF5TextEditor.5.dylib`KateViewInternal::textHintTimeout(this=0x00007f855d4cc940) + 311 at kateviewinternal.cpp:3101 [opt] frame #23: 0x0000000107377f35 libKF5TextEditor.5.dylib`KateViewInternal::qt_static_metacall(_o=<unavailable>, _c=<unavailable>, _id=<unavailable>, _a=<unavailable>) + 885 at moc_kateviewinternal.cpp:200 [opt] frame #24: 0x00000001097f98a4 QtCore`QMetaObject::activate(sender="00:00:00", signalOffset=<unavailable>, local_signal_index=<unavailable>, argv=<unavailable>) + 3028 at qobject.cpp:3730 [opt] frame #25: 0x00000001097f1ba0 QtCore`QObject::event(this="00:00:00", e=<unavailable>) + 48 at qobject.cpp:1237 [opt] frame #26: 0x000000010866e1e6 QtWidgets`QApplicationPrivate::notify_helper(this=<unavailable>, receiver="00:00:00", e="00:00:00") + 294 at qapplication.cpp:3804 [opt] frame #27: 0x0000000108671726 QtWidgets`QApplication::notify(this=<unavailable>, receiver=<unavailable>, e=<unavailable>) + 8470 at qapplication.cpp:3767 [opt] frame #28: 0x00000001097c5587 QtCore`QCoreApplication::notifyInternal2(receiver="00:00:00", event="00:00:00") + 167 at qcoreapplication.cpp:1020 [opt] frame #29: 0x000000010981e7a1 QtCore`QTimerInfoList::activateTimers() [inlined] QCoreApplication::sendEvent(receiver=<unavailable>, event=0x0000000109a30150) + 1329 at qcoreapplication.h:225 [opt] frame #30: 0x000000010981e794 QtCore`QTimerInfoList::activateTimers(this="00:00:00") + 1316 at qtimerinfo_unix.cpp:637 [opt] frame #31: 0x0000000112ff8482 libqcocoa.dylib`QCocoaEventDispatcherPrivate::activateTimersSourceCallback(info=0x00007f85594606a0) + 18 at qcocoaeventdispatcher.mm:119 [opt] frame #32: 0x00007fff866c35b1 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17 frame #33: 0x00007fff866b4c62 CoreFoundation`__CFRunLoopDoSources0 + 242 frame #34: 0x00007fff866b43ef CoreFoundation`__CFRunLoopRun + 831 frame #35: 0x00007fff866b3e75 CoreFoundation`CFRunLoopRunSpecific + 309 frame #36: 0x00007fff8a9d7a0d HIToolbox`RunCurrentEventLoopInMode + 226 frame #37: 0x00007fff8a9d77b7 HIToolbox`ReceiveNextEventCommon + 479 frame #38: 0x00007fff8a9d75bc HIToolbox`_BlockUntilNextEventMatchingListInModeWithFilter + 65 frame #39: 0x00007fff8e86f24e AppKit`_DPSNextEvent + 1434 frame #40: 0x00007fff8e86e89b AppKit`-[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] + 122 frame #41: 0x00007fff8e86299c AppKit`-[NSApplication run] + 553 frame #42: 0x0000000112ff908d libqcocoa.dylib`QCocoaEventDispatcher::processEvents(this=0x00007f8559463a30, flags=<unavailable>) + 2189 at qcocoaeventdispatcher.mm:416 [opt] frame #43: 0x00000001097c19a1 QtCore`QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) [inlined] QEventLoop::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) + 401 at qeventloop.cpp:128 [opt] frame #44: 0x00000001097c1984 QtCore`QEventLoop::exec(this=0x00007fff5969ada0, flags=<unavailable>) + 372 at qeventloop.cpp:204 [opt] frame #45: 0x00000001097c5c15 QtCore`QCoreApplication::exec() + 325 at qcoreapplication.cpp:1290 [opt] > Ideally this operation would be performed on a thread of its own, while the
> main thread continues to process events and aborts the operation in reaction
> to certain events (text input or focus movement that changes the expression
> being parsed, for instance).
Maybe it'd be easier to check for certain events at appropriate locations in the code which is taking time, and abort the operation within some timeout/grace period after such events?
Created attachment 102145 [details]
simple patch to prevent beachballing
It may be useful to add a processEvents() call in this function's foreach loop too. sendPostedEvents() may not even be required there.
static ProblemPointer findProblemUnderCursor(TopDUContext* topContext, KTextEditor::Cursor position)
{
const auto top = ReferencedTopDUContext(topContext);
foreach (auto problem, DUChainUtils::allProblemsForContext(top)) {
if (problem->rangeInCurrentRevision().contains(position)) {
return problem;
}
}
return {};
}
Agreed, we/I should look into this issue. I'm afraid your patch merely serves as a work-around though. Yes, that's exactly what it is - but you can also provoke a nice fireworks display of context browser tooltips with it ;) It might resemble more of a fix if it's possible to check after processing the events if an action was taken which should abort the ongoing operation. Not sure how you'd do that, but I'm not sure either if there's a truly better, different solution. From what I see, the expensive operation is launched as part of a tooltip display callback, meaning there isn't much else that callback can do when you offload the expensive content creation operation to a background thread. Unless you can create and show the tooltip from a background job? I'd be happy to test if you have something that should work. *** This bug has been marked as a duplicate of bug 372040 *** |