clang's CXTranslationUnit_PrecompiledPreamble madness

Kevin Funk kfunk at kde.org
Sat Jan 9 21:35:53 UTC 2016


On Saturday, January 09, 2016 06:28:02 PM Milian Wolff wrote:
> Hey all, esp. Sergey, Kevin and Olivier.
> 
> After quite some time I finally sat down today to write a proper benchmark
> for our clang-based code completion. It's relatively slow for big C++
> include chains as we all know. It's still bearable most of the time where
> it's in the ~250ms space on my machine, but definitely noticeable and of
> course worse on slower machines.
> 
> Now during the recent Qt World Summit I chatted with Marco Bubke who's
> nowadays working on Qt Creator's clang code model. One nugget he shared with
> me is that Clang's C API won't actually create a preamble if you don't call
> clang_reparseTranslationUnit after the initial clang_parseTranslationUnit2
> call...
> 
> With my new benchmark you can see the impact this has, on a KDev* build
> without any optimizations:
> 
> no preamble:
> 
> RESULT : BenchCodeCompletion::benchCodeCompletion():"empty":
>      2.4 msecs per iteration (total: 79, iterations: 32)
> --
> RESULT : BenchCodeCompletion::benchCodeCompletion():"stl":
>      171 msecs per iteration (total: 171, iterations: 1)
> --
> RESULT : BenchCodeCompletion::benchCodeCompletion():"clib":
>      66 msecs per iteration (total: 66, iterations: 1)
> 
> with preamble:
> 
> RESULT : BenchCodeCompletion::benchCodeCompletion():"empty":
>      1.7 msecs per iteration (total: 55, iterations: 32)
> --
> RESULT : BenchCodeCompletion::benchCodeCompletion():"stl":
>      9.7 msecs per iteration (total: 78, iterations: 8)
> --
> RESULT : BenchCodeCompletion::benchCodeCompletion():"clib":
>      18 msecs per iteration (total: 74, iterations: 4)
> 
> So from this I think it's pretty clear that we want this. The reason I write
> this lengthy mail instead of just committing

Thanks for the benchmarks. Numbers are always good.

> diff --git a/languages/clang/duchain/parsesession.cpp b/languages/clang/
> duchain/parsesession.cpp
> index f992a1c..e6c7385 100644
> --- a/languages/clang/duchain/parsesession.cpp
> +++ b/languages/clang/duchain/parsesession.cpp
> @@ -237,6 +237,7 @@ ParseSessionData::ParseSessionData(const
> QVector<UnsavedFile>& unsavedFiles, Cla
>      }
> 
>      if (m_unit) {
> +        clang_reparseTranslationUnit(m_unit, unsaved.size(),
> unsaved.data(), clang_defaultReparseOptions(m_unit));
>          setUnit(m_unit);
>          m_environment = environment;
> 
> is that it breaks quite some unit tests, even with Clang 3.7.0:
> 
> FAIL!  : TestCodeCompletion::testVariableScope() Compared values are not the
> same
>    Actual   (tester.items.size()): 3
>    Expected (4)                  : 4
>    Loc:
> [/home/milian/projects/kf5/src/extragear/kdevelop/kdevelop/languages/
> clang/tests/test_codecompletion.cpp(988)]
> FAIL!  : TestCodeCompletion::testCompleteFunction(add-parens) Compared
> values are not the same
>    Actual   (view->document()->text()): "int foo();\nint main()
> {\nmain()\n}" Expected (expectedCode)            : "int foo();\nint main()
> {\nfoo()\n}" Loc:
> [/home/milian/projects/kf5/src/extragear/kdevelop/kdevelop/languages/
> clang/tests/test_codecompletion.cpp(1100)]
> FAIL!  : TestCodeCompletion::testCompleteFunction(keep-parens) Compared
> values are not the same
>    Actual   (view->document()->text()): "int foo();\nint main()
> {\nfoo();\n}" Expected (expectedCode)            : "int foo();\nint main()
> {\nmain();\n}" Loc:
> [/home/milian/projects/kf5/src/extragear/kdevelop/kdevelop/languages/
> clang/tests/test_codecompletion.cpp(1100)]
> FAIL!  : TestDUChain::testReparseUnchanged(template-default-parameters)
> 'implCtx->problems().isEmpty()' returned FALSE. ()
>    Loc:
> [/home/milian/projects/kf5/src/extragear/kdevelop/kdevelop/languages/
> clang/tests/test_duchain.cpp(1397)]
> 
> So I think it looks like we'll have to dig into Clang to fix these issues
> and then commit the patch above. Anyone interested in helping out? Also if
> you have access to older or newer clang, please try the above and see what
> it breaks.

The testCompleteFunction is flaky for me, very likely timing related.

I had runs with zero failures, then with 1, and sometimes with the 3 failures 
you get there.
 
> Furthermore, note that we already do generate a preamble file if the user
> edits the file! So the above test issues are affecting our users *now*.
> Maybe we want to commit the patch after all?

The test case from above:

int foo();
int main()
{
    <complete here>    
    return 0;
}

... works fine for me *with* your patch in a normal KDevelop session. I get 
(foo, main) as completion items, if I just press enter I get the desired 
result: foo().

I guess its just our tests which are broken...?

Am I missing something?

Cheers,
Kevin

-- 
Kevin Funk | kfunk at kde.org | http://kfunk.org
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 181 bytes
Desc: This is a digitally signed message part.
URL: <http://mail.kde.org/pipermail/kdevelop-devel/attachments/20160109/dcb1a69f/attachment-0001.sig>


More information about the KDevelop-devel mailing list