The test lldb/packages/Python/lldbsuite/test/lang/cpp/member-and-local-vars-with-same-name/main.cpp is testing this feature, so you should get a 10 (instead of a correct 12345) when you break in main.cpp:31 in this test and eval "expr a" while you have this feature disabled. At least for me that's the case.
- Raphael Am Do., 22. Aug. 2019 um 16:31 Uhr schrieb Scott Funkenhauser via lldb-dev <lldb-dev@lists.llvm.org>: > > Hey Jim, > > We just noticed that 'target.experimental.inject-local-vars' is true by > default. If we disable that experimental the performance for expression > evaluation is significantly better. > > From the flag description: > "If true, inject local variables explicitly into the expression text. This > will fix symbol resolution when there are name collisions between ivars and > local variables. But it can make expressions run much more slowly." > > I put together a simple example: > class bar { > public: > int foo = 2; > int Run(int foo) { > return foo + 1; > } > }; > > Evaluating 'foo' when stopped in bar.Run() seems to work as expected. Is > there something I'm not capturing in my example? Do you have an example of a > name collision that the experimental flag fixes? > > > On Mon, Jul 15, 2019 at 1:53 PM Guilherme Andrade via lldb-dev > <lldb-dev@lists.llvm.org> wrote: >> >> Gábor, >> Thanks for pointing this out to me. The AST changes - the resulting log >> increases from 7k lines to 11k. I also verified that the fallback branch is >> executed. 18k iterations during the first evaluation and 93k afterwards. >> However, that only results in a couple extra milliseconds slowness (~ 4 ms), >> whereas the overall performance hit is in the order of hundreds. >> >> Jim, >> Thank you for the explanation. I think I understand the lazy approach for >> types realization, but it is still not clear to me how that could cause the >> performance to degrade. If we encounter an already realized type, won't that >> save us work and make things run faster? Do you know of other points in the >> code that could be particularly sensitive to the realized types pool size >> (something like the branch Gábor mentioned)? >> >> On Fri, Jul 12, 2019 at 6:08 AM Gábor Márton <martongab...@gmail.com> wrote: >>> >>> Guilherme, >>> >>> Could you please check if you have any structural differences between the >>> ASTs you see when >>> 1) you first evaluate your expression at breakpoint A >>> 2) you evaluate your expression the second time at breakpoint A ? >>> The AST of the expression evaluator's context is dumped once a TagDecl is >>> completed, but you need to enable a specific logging: (log enable lldb ast). >>> >>> I have a theory about the root cause of the slowness you experience, but it >>> requires proof from your test scenario. >>> There are known problems with the lookup we use in LLDB [1]. >>> If the lookup mechanism cannot find a symbol then clang::ASTImporter will >>> create a new AST node. >>> Thus I am expecting a growing AST in your case at 2) with duplicated and >>> redundant AST nodes. >>> Why would the grown AST results in any slowness? >>> Because the lookup we use is in `clang::DeclContext::localUncachedLookup()` >>> and it has a fallback branch which I assume is executed in your case: >>> ``` >>> // Slow case: grovel through the declarations in our chain looking for >>> // matches. >>> // FIXME: If we have lazy external declarations, this will not find them! >>> // FIXME: Should we CollectAllContexts and walk them all here? >>> for (Decl *D = FirstDecl; D; D = D->getNextDeclInContext()) { >>> if (auto *ND = dyn_cast<NamedDecl>(D)) >>> if (ND->getDeclName() == Name) >>> Results.push_back(ND); >>> } >>> ``` >>> This for loop does a linear search on the list of the decls of a decl >>> context, which explains the slowing factor as the AST grows. >>> I wounder if you could help proving this theorem by first checking if the >>> AST grows and if yes then checking if this linear search is executed or not. >>> >>> [1] If a symbol is in an `extern "C"` block then the existing lookup fails >>> to find it. I try to fix it in https://reviews.llvm.org/D61333 >>> >>> Thanks, >>> Gabor >>> >>> On Thu, Jul 11, 2019 at 8:24 PM Jim Ingham via lldb-dev >>> <lldb-dev@lists.llvm.org> wrote: >>>> >>>> lldb realizes types from DWARF lazily. So for instance, if an expression >>>> refers to a pointer to type Foo, we won't necessarily realize the full >>>> type of Foo from DWARF to parse that expression. Then if you write a >>>> second expression that accesses a member of an object of type Foo, we will >>>> realize the full type for Foo. Then if you run the first expression >>>> again, the pointer to Foo type in the lldb type system will now point to a >>>> realized type of Foo. That should not make any difference, since if we >>>> were right the first time that we didn't need to know anything about Foo, >>>> it shouldn't matter whether the full type is realized or not. >>>> >>>> Similarly, the "expression with no side effects" could have also caused >>>> lldb to realize any number of other types. We find names from type >>>> information in two ways: looking in the realized types, and looking in the >>>> name indexes we read from DWARF or (on systems without accelerator tables) >>>> from indexing the DWARF manually. So the expression with no side effects >>>> will change the types in the realized types pool. That also "should not >>>> matter" because if the expression X was looking up by name, the lookup >>>> through the name indexes when the type wasn't realized yet should be >>>> equivalent to the lookup in the realized types. >>>> >>>> We really have no choice but to realize types lazily in this way, the >>>> debugger would just run way too slowly on big projects if we didn't. So >>>> the fact that one expression can change the state of the type system for a >>>> subsequent expression is a fact of life for lldb. But if the lookup >>>> mechanism is working properly, then these changes shouldn't matter. OTOH >>>> shouldn't and don't are not quite the same... >>>> >>>> Jim >>>> >>>> >>>> > On Jul 11, 2019, at 9:53 AM, Guilherme Andrade <guiandr...@google.com> >>>> > wrote: >>>> > >>>> > Speaking more generally, can evaluating an expression with no side >>>> > effects affect the outcome of subsequent evaluations? I.e, is it >>>> > possible for the expression evaluation X to produce different results in >>>> > the following scenarios? >>>> > >>>> > Scenario 1: <set of instructions A> <expression evaluation with no side >>>> > effects> <set of instructions B> <expression evaluation X> >>>> > Scenario 2: <set of instructions A> <set of instructions B> <expression >>>> > evaluation X> >>>> > >>>> > Thanks! >>>> > >>>> > On Tue, Jul 9, 2019 at 2:52 PM Guilherme Andrade <guiandr...@google.com> >>>> > wrote: >>>> > Thanks for looking into this, Jason. I ended up realizing that it isn't >>>> > about the number of evaluations; it is the exact location of the >>>> > breakpoints that matters. >>>> > >>>> > I'm being able to consistently reproduce this by having two breakpoints >>>> > (A and B) inside the same function, but B being inside the scope of a >>>> > for loop that defines a couple extra variables. The first evaluation of >>>> > 'undefinedVariable' at breakpoint A generates the following >>>> > FindExternalLexicalDecls calls: >>>> > >>>> > FindExternalLexicalDecls[5] on (ASTContext*)000001566104F030 in 'Type0' >>>> > (CXXRecordDecl*)0000015668964438 >>>> > FindExternalLexicalDecls[6] on (ASTContext*)000001566104F030 in 'Type6' >>>> > (CXXRecordDecl*)0000015668961BA8 >>>> > FindExternalLexicalDecls[7] on (ASTContext*)000001566104F030 in 'Type7' >>>> > (CXXRecordDecl*)0000015668961A68 >>>> > FindExternalLexicalDecls[8] on (ASTContext*)000001566104F030 in 'Type8' >>>> > (CXXRecordDecl*)0000015674F56208 >>>> > FindExternalLexicalDecls[9] on (ASTContext*)000001566104F030 in 'Type9' >>>> > (ClassTemplateSpecializationDecl*)0000015674F56CD0 >>>> > FindExternalLexicalDecls[10] on (ASTContext*)000001566104F030 in >>>> > 'Type10' (CXXRecordDecl*)0000015668964300 >>>> > FindExternalLexicalDecls[11] on (ASTContext*)000001566104F030 in >>>> > 'Type10' (CXXRecordDecl*)0000015668964300 >>>> > FindExternalLexicalDecls[12] on (ASTContext*)000001566104F030 in 'Type0' >>>> > (CXXRecordDecl*)0000015668964438 >>>> > FindExternalLexicalDecls[13] on (ASTContext*)000001566104F030 in >>>> > 'Type11' (EnumDecl*)0000015674F62778 >>>> > >>>> > Then, the evaluation at breakpoint B generates: >>>> > >>>> > FindExternalLexicalDecls[19] on (ASTContext*)000001F1F6275320 in 'Type0' >>>> > (CXXRecordDecl*)000001F1EA798868 >>>> > FindExternalLexicalDecls[20] on (ASTContext*)000001F1F6275320 in 'Type1' >>>> > (CXXRecordDecl*)000001F1EA799098 >>>> > FindExternalLexicalDecls[21] on (ASTContext*)000001F1F6275320 in 'Type2' >>>> > (ClassTemplateSpecializationDecl*)000001F1EA7A0D50 >>>> > FindExternalLexicalDecls[22] on (ASTContext*)000001F1F6275320 in 'Type3' >>>> > (CXXRecordDecl*)000001F1EA79D818 >>>> > FindExternalLexicalDecls[23] on (ASTContext*)000001F1F6275320 in 'Type4' >>>> > (CXXRecordDecl*)000001F1EA79D548 >>>> > FindExternalLexicalDecls[24] on (ASTContext*)000001F1F6275320 in 'Type5' >>>> > (CXXRecordDecl*)000001F1EA7A2A08 >>>> > FindExternalLexicalDecls[25] on (ASTContext*)000001F1F6275320 in 'Type6' >>>> > (CXXRecordDecl*)000001F1EA7BB368 >>>> > FindExternalLexicalDecls[26] on (ASTContext*)000001F1F6275320 in 'Type7' >>>> > (CXXRecordDecl*)000001F1EA7BB228 >>>> > FindExternalLexicalDecls[27] on (ASTContext*)000001F1F6275320 in 'Type8' >>>> > (CXXRecordDecl*)000001F1F68B9088 >>>> > FindExternalLexicalDecls[28] on (ASTContext*)000001F1F6275320 in 'Type9' >>>> > (ClassTemplateSpecializationDecl*)000001F1F68B2AC0 >>>> > FindExternalLexicalDecls[29] on (ASTContext*)000001F1F6275320 in >>>> > 'Type10' (CXXRecordDecl*)000001F1EA798730 >>>> > FindExternalLexicalDecls[30] on (ASTContext*)000001F1F6275320 in >>>> > 'Type10' (CXXRecordDecl*)000001F1EA798730 >>>> > FindExternalLexicalDecls[31] on (ASTContext*)000001F1F6275320 in 'Type0' >>>> > (CXXRecordDecl*)000001F1EA798868 >>>> > FindExternalLexicalDecls[32] on (ASTContext*)000001F1F6275320 in >>>> > 'Type11' (EnumDecl*)000001F1F68CB3E0 >>>> > FindExternalLexicalDecls[33] on (ASTContext*)000001F1F6275320 in >>>> > 'Type12' (CXXRecordDecl*)000001F1E2351F48 >>>> > >>>> > And the subsequent evaluations at breakpoint A, which are slower, >>>> > produce: >>>> > >>>> > FindExternalLexicalDecls[91] on (ASTContext*)000001566104F030 in 'Type0' >>>> > (CXXRecordDecl*)000001566895C3B8 >>>> > FindExternalLexicalDecls[92] on (ASTContext*)000001566104F030 in 'Type1' >>>> > (CXXRecordDecl*)000001566895CBE8 >>>> > FindExternalLexicalDecls[93] on (ASTContext*)000001566104F030 in 'Type2' >>>> > (ClassTemplateSpecializationDecl*)00000156689678D0 >>>> > FindExternalLexicalDecls[94] on (ASTContext*)000001566104F030 in 'Type3' >>>> > (CXXRecordDecl*)0000015668964398 >>>> > FindExternalLexicalDecls[95] on (ASTContext*)000001566104F030 in 'Type4' >>>> > (CXXRecordDecl*)00000156689640C8 >>>> > FindExternalLexicalDecls[96] on (ASTContext*)000001566104F030 in 'Type5' >>>> > (CXXRecordDecl*)0000015674F608B8 >>>> > FindExternalLexicalDecls[97] on (ASTContext*)000001566104F030 in 'Type6' >>>> > (CXXRecordDecl*)0000015674F731B8 >>>> > FindExternalLexicalDecls[98] on (ASTContext*)000001566104F030 in 'Type7' >>>> > (CXXRecordDecl*)0000015674F73078 >>>> > FindExternalLexicalDecls[99] on (ASTContext*)000001566104F030 in 'Type8' >>>> > (CXXRecordDecl*)0000015674F7B278 >>>> > FindExternalLexicalDecls[100] on (ASTContext*)000001566104F030 in >>>> > 'Type9' (ClassTemplateSpecializationDecl*)0000015674F78CF0 >>>> > FindExternalLexicalDecls[101] on (ASTContext*)000001566104F030 in >>>> > 'Type10' (CXXRecordDecl*)000001566895C280 >>>> > FindExternalLexicalDecls[102] on (ASTContext*)000001566104F030 in >>>> > 'Type10' (CXXRecordDecl*)000001566895C280 >>>> > FindExternalLexicalDecls[103] on (ASTContext*)000001566104F030 in >>>> > 'Type0' (CXXRecordDecl*)000001566895C3B8 >>>> > FindExternalLexicalDecls[104] on (ASTContext*)000001566104F030 in >>>> > 'Type11' (EnumDecl*)0000015674F81510 >>>> > >>>> > The FindExternalVisibleDecls entries remain the same among all >>>> > evaluations at breakpoint A. >>>> > >>>> > So, Jim, if symbols are getting added at B or types are being completed, >>>> > then the extra FindExternalLexicalDecls calls for Type1-5 is intended >>>> > behavior? >>>> > >>>> > On Mon, Jul 8, 2019 at 7:04 PM Jim Ingham <jing...@apple.com> wrote: >>>> > Are any sources for symbols getting added to the process as you go >>>> > along, like new shared library loads? You are asking for a non-existent >>>> > name, so every new source of debug info is a new place to look. >>>> > >>>> > It's also possible that we are completing some types during the course >>>> > of the expression evaluation, and then the newly completed types become >>>> > themselves new places to look for this non-existent name. >>>> > >>>> > You can see what is getting looked up by turning in the expression log >>>> > (log enable lldb expr) then looking for the FindExternalVisibleDecls >>>> > entries. >>>> > >>>> > Jim >>>> > >>>> > >>>> > > On Jul 8, 2019, at 3:33 PM, Jason Molenda via lldb-dev >>>> > > <lldb-dev@lists.llvm.org> wrote: >>>> > > >>>> > > Hm, that's interesting. >>>> > > >>>> > > I tried running a debug lldb on /bin/ls. then I attached from another >>>> > > lldb. I put a breakpoint on >>>> > > CommandObjectTargetModulesLookup::DoExecute and resumed execution. In >>>> > > the debuggee lldb, I did >>>> > > >>>> > > tar mod loo -a 0 >>>> > > >>>> > > >>>> > > and auto-repeated return so the same command would be executed over >>>> > > and over. >>>> > > >>>> > > In the debugger lldb, I tried adding a command to the breakpoint, >>>> > > >>>> > > br comm add >>>> > > p does_not_exist >>>> > > DONE >>>> > > >>>> > > and continuing - after a couple dozen times, I didn't see a slowdown. >>>> > > I tried adding a breakpoint condition, >>>> > > >>>> > > br mod -c 'doesNotExist == 1' 1 >>>> > > >>>> > > and continuing, and didn't see a slowdown after a few dozen >>>> > > repetitions. >>>> > > >>>> > > I'm on macOS using .o file DWARF debugging. >>>> > > >>>> > > I'm sure there's a bug here, but it may be more specific to the >>>> > > platform and type of debug info that you're using? It could be that >>>> > > lldb is too small of a project to repo this problem too. >>>> > > >>>> > > >>>> > > >>>> > >> On Jul 4, 2019, at 11:38 AM, Guilherme Andrade via lldb-dev >>>> > >> <lldb-dev@lists.llvm.org> wrote: >>>> > >> >>>> > >> I have two breakpoint inside methods that are called every frame (C++ >>>> > >> project using Unreal), and every time one of them is reached, I >>>> > >> evaluate one expression (I'm being able to reproduce this using an >>>> > >> undefined name, say "undefinedVariable"). After a few iterations >>>> > >> (usually tens), the time it takes for LLDB to say that name doesn't >>>> > >> exist increases, despite being the same expression, at the same >>>> > >> breakpoint and the call stack remaining unchanged. >>>> > >> >>>> > >> I've noticed that the number of lexical Decl queries and imports >>>> > >> conducted by Clang reported in 'Local metrics' increase. >>>> > >> >>>> > >> They go from: >>>> > >> Number of visible Decl queries by name : 29 >>>> > >> Number of lexical Decl queries : 9 >>>> > >> Number of imports initiated by LLDB : 15 >>>> > >> Number of imports conducted by Clang : 827 >>>> > >> Number of Decls completed : 5 >>>> > >> Number of records laid out : 2 >>>> > >> >>>> > >> To: >>>> > >> Number of visible Decl queries by name : 29 >>>> > >> Number of lexical Decl queries : 14 >>>> > >> Number of imports initiated by LLDB : 15 >>>> > >> Number of imports conducted by Clang : 1342 >>>> > >> Number of Decls completed : 5 >>>> > >> Number of records laid out : 2 >>>> > >> >>>> > >> Also, the number of SymbolFileDWARF operations in the logs jumps from >>>> > >> 366 to 406. >>>> > >> >>>> > >> So, I've got two questions. 1) Is it safe to say that those extra >>>> > >> imports and Decl queries are responsible for the performance loss? 2) >>>> > >> Why do they happen? >>>> > >> >>>> > >> Thanks! >>>> > >> _______________________________________________ >>>> > >> lldb-dev mailing list >>>> > >> lldb-dev@lists.llvm.org >>>> > >> https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev >>>> > > >>>> > > _______________________________________________ >>>> > > lldb-dev mailing list >>>> > > lldb-dev@lists.llvm.org >>>> > > https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev >>>> > >>>> > >>>> > -- >>>> > Guilherme Andrade | Software Engineer | guiandr...@google.com | Google >>>> > Waterloo, Canada >>>> >>>> _______________________________________________ >>>> lldb-dev mailing list >>>> lldb-dev@lists.llvm.org >>>> https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev >> >> _______________________________________________ >> lldb-dev mailing list >> lldb-dev@lists.llvm.org >> https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev > > _______________________________________________ > lldb-dev mailing list > lldb-dev@lists.llvm.org > https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev _______________________________________________ lldb-dev mailing list lldb-dev@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev