Bug 386720 - Ubuntu 17.10 becomes very slow / unresponsive / freezes / hangs when opening a small C++ project that uses Boost
Summary: Ubuntu 17.10 becomes very slow / unresponsive / freezes / hangs when opening ...
Status: RESOLVED FIXED
Alias: None
Product: kdevelop
Classification: Applications
Component: general (show other bugs)
Version: git master
Platform: Other Linux
: NOR grave
Target Milestone: ---
Assignee: kdevelop-bugs-null
URL:
Keywords:
: 389078 (view as bug list)
Depends on:
Blocks:
 
Reported: 2017-11-10 20:21 UTC by Ciro Santilli
Modified: 2018-01-16 23:31 UTC (History)
2 users (show)

See Also:
Latest Commit:
Version Fixed In: 5.2.2


Attachments
gdb stacktrace (19.29 KB, text/plain)
2018-01-08 16:51 UTC, Angelo Puglisi
Details
stacktrace with libclang symbols (14.17 KB, text/plain)
2018-01-08 17:13 UTC, Angelo Puglisi
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Ciro Santilli 2017-11-10 20:21:23 UTC
d1666b51297597eae00f58a6e43d9cf4fe0f7d3f (post v5.2.0)

Build following https://community.kde.org/KDevelop/HowToCompile_v5

Open project, choose: https://github.com/cirosantilli/general-game-ai/tree/c1b1f143a5ef2ddf7ddb80cadbe47ee670013dd7 which is a small C++ project that uses Boost.

GUI shows 2% parsing on bottom right, is slow / stuck there, ps says it uses 33% of CPU and memory.

4Gb RAM, Intel(R) Core(TM) i5-3210M CPU @ 2.50GHz, so I know not much, but even Eclipse runs. But I want libllvm parsing :-(
Comment 1 Angelo Puglisi 2018-01-08 16:51:56 UTC
Created attachment 109737 [details]
gdb stacktrace

I've got an unusually high CPU usage, kdevelop 5.2.1.

I got two threads at 100%, background parser stuck at 0%:
>  PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND                                                                            
> 5823 angelo    20   0 2817224 1,019g 347332 R 99,9  6,5  10:59.67 /usr/bin/kdevelop                                                                  
> 5822 angelo    20   0 2817224 1,019g 347332 R 99,9  6,5  12:04.31 /usr/bin/kdevelop

It seems something related to libclang, as you can see in attached stacktrace
Comment 2 Angelo Puglisi 2018-01-08 17:13:29 UTC
Created attachment 109738 [details]
stacktrace with libclang symbols

Attached another stacktrace, now with libclang debugging symbols. I hope it helps.

>  PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND
>11426 angelo    20   0 2743056 998024 343924 R 99,7  6,1   4:58.01 kdevelop
>11427 angelo    20   0 2743056 998024 343924 R 99,7  6,1   4:41.15 kdevelop
Comment 3 Milian Wolff 2018-01-09 11:53:43 UTC
Can you check what file is triggering this? To do that, enable the language debug output and start KDevelop form the command line:

$ nano ~/config/QtProject/qtlogging.ini
[Rules]
kdevplatform.language.debug=true
$ kdevelop -s ... |& grep -i parse

So what files are being parsed at the end? How many problems do they have? Are the files really large?
Comment 4 Angelo Puglisi 2018-01-09 14:35:20 UTC
(In reply to Milian Wolff from comment #3)
> Can you check what file is triggering this? To do that, enable the language
> debug output and start KDevelop form the command line:
> 
> $ nano ~/config/QtProject/qtlogging.ini
> [Rules]
> kdevplatform.language.debug=true
> $ kdevelop -s ... |& grep -i parse
> 
> So what files are being parsed at the end? How many problems do they have?
> Are the files really large?

I see a few of those:
> kdevplatform.language: creating parse-job <file path> new count of active parse-jobs: <n>
but I can't see anything suggesting that there are any problems.
I have those lines only for the files I have opened.

Then I have a couple of:
> kdevplatform.language: Aborting cleanup because language plugin is still parsing: "clang"
and nothing more...


I have a kde neon user edition, kdevelop is 4:5.2.1-0neon+16.04+xenial+build38 and libclang1-5.0 1:5.0-3~16.04.1
Comment 5 Milian Wolff 2018-01-09 14:56:02 UTC
Is the first kind of output repeating, even while you think kdevelop is frozen? Then it's not frozen and actually does useful work. You simply need to wait. It should take roughly (hopefully a bit less) as long to parse the project in KDevelop as it would take to compile it.

It would only be a bug if you'd see this output stopping at some files and not going anywhere, while CPU usage is high.

The last kind of output is OK, it's internal debug output and expected. You can ignore it.
Comment 6 Angelo Puglisi 2018-01-09 15:02:45 UTC
(In reply to Milian Wolff from comment #5)
> Is the first kind of output repeating, even while you think kdevelop is
> frozen? Then it's not frozen and actually does useful work. You simply need
> to wait. It should take roughly (hopefully a bit less) as long to parse the
> project in KDevelop as it would take to compile it.
> 
> It would only be a bug if you'd see this output stopping at some files and
> not going anywhere, while CPU usage is high.
> 
> The last kind of output is OK, it's internal debug output and expected. You
> can ignore it.

My kdevelop is not frozen, it's still working but the parser is stuck at 0% and I have the parser thread at 100% all the time (I mean my whole working day).
Except from the last line I have no other output.


I tried to reproduce the issue with a simpler project, including some boost headers I use, but I have only a cpu peak for a couple of seconds and then it stops.
I'll try to figure out something to be helpful
Comment 7 Milian Wolff 2018-01-09 15:06:55 UTC
Confusion: I don't mean a GUI freeze, I mean that the parser is frozen at 0% as you describe. If that happens, then the output of the form

> kdevplatform.language: creating parse-job <file path> new count of active parse-jobs: <n>

should stop eventually and the last two lines would indicate which files are being parsed.
Comment 8 Milian Wolff 2018-01-09 17:34:34 UTC
Reproduced it now in a project of mine. There, the reason is that we get *tons* of problems due to broken include paths, which then trigger lots and lots of "include file not found". If that happens deep in the include stack, the problem also have tons of child diagnostics (i.e. "included from ..."). These child diagnostics have only a cursor, not a range, and then the hack to compute a range out of it seems to be quite slow:

auto nextLocation = clang_getLocation(unit, file, line, column + 100);
Comment 9 Milian Wolff 2018-01-09 18:02:49 UTC
OK, it's not the hack, it's the sheer amount of errors in my case. I get thousands of ClangProblems (dozens per file, each with up to hundreds of child diagnostics) for a single TU. We should probably limit this somehow and bail out if something goes wrong :-/

What's more:

- we add the IncludeFileNotFoundProblem errors to *all* files in the TU. Maybe we should only do that for the main file? This is quite costly. Or we cache the problem pointers

- we sometimes get plain garbadge from libclang: https://i.imgur.com/Kd7ZCsS.png 
I even see this one, which is epic: <somefile> "unused parameter 'frame' [-Wunused-parameter]" child diagnostics: 702

suffice to say, the child diagnostics are bogus like in the screenshot

Sigh, let's see how this can be fixed and/or work-arounded :-/
Comment 10 Milian Wolff 2018-01-09 18:57:35 UTC
if you can, please try to apply https://phabricator.kde.org/D9772 and test whether it improves the situation for you
Comment 11 Milian Wolff 2018-01-10 10:37:22 UTC
Git commit f2a6941e086cdf506c8fb1798c52982bff43792d by Milian Wolff.
Committed on 10/01/2018 at 10:37.
Pushed by mwolff into branch '5.2'.

Cache ProblemPointers per translation unit

Summary:
For visibility purposes, all 'inclue file not found' errors are
associated with all files in a TU, since these usually completely
break the interpretation of a file. But in some situations, this
triggers a severe performance degradation:

When the TU has a deep include stack depth and a file is not found
somewhere at the bottom of the stack, then it will have one child
diagnostic for every "included from ..." file higher up in the stack.
Now if we would repeatedly build and intern the KDevelop::Problem
representation for these diagnostics, for every file in the TU, we
sometimes ended up spending *minutes* to create all the problems
in ParseSession::problemsForFile!

To workaround this situation, cache the ProblemPointer in the
ParseSessionData for a given translation unit. This way, we will
only convert a given diagnostic and its child diagnostics once per TU
instead of once per file contained in a TU.

In my case this brings down the time spent in problemsForFile for a
single TU from ~7min (sic!) down to ~12s. While the latter is still
a lot, this is already much more bearable.

Reviewers: #kdevelop

Subscribers: kdevelop-devel

Differential Revision: https://phabricator.kde.org/D9772

M  +8    -1    plugins/clang/duchain/parsesession.cpp
M  +2    -0    plugins/clang/duchain/parsesession.h

https://commits.kde.org/kdevelop/f2a6941e086cdf506c8fb1798c52982bff43792d
Comment 12 Kevin Funk 2018-01-16 23:29:50 UTC
*** Bug 389078 has been marked as a duplicate of this bug. ***