Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [cdt-dev] Freeze invisible GDB variable objects

Some more information about this topic:

As mentioned before, when scrolling down in a expanded struct CDT immediately gets the values of the newly appearing struct members. I guess this is initiated by the 'SWT Tree's 'virtual' feature (by which the tree is not created up-front, but only when the items are actually shown). Unfortunately, once the items were shown, no more SWT events are processed by CDT when scrolling up and down (I enabled various tracing levels - but no traces appear when scrolling). => Therefore, nothing within CDT seems to be aware of which items in a tree are visible and which are hidden (unless I just didn't find that piece of code).

Furthermore: As mentioned in a previous post, CDT executes a '-var-update 1 varX' after certain debug event (e.g. after a single step). This causes GDB to read the values of all non-freezed members of 'varX' from the embedded system. One important thing to be aware of, is the fact that GDB does not even refresh the value of a frozen variable (i.e. member of a struct) when it's value is explicitly requested. That makes sense, but it complicates the solution for this issue: Whenever the user scrolls within the members of a struct while some of the members are frozen it's not sufficient to explicitly fetch the values of the newly appearing members, because GDB would still return old values for them. Instead, CDT would need to first change the frozen state of these variables followed by a '-var-update 1 varX'.

Summarized:
- We'd need to react on scrolling (and any other graphical event that may change visibility of expressions. That could probably be done by registering to the various SWT events)
 - Upon graphical changes, we'd need to:
   - check which (sub)expressions are visible
   - update the 'frozen' status
   - execute a '-var-update'

I've no implementation for this, but I've implemented a prototype that does parts of this: After every debug event, in VariableVMNode.update(final IExpressionUpdate update), it walks through the TreeItems of the expression view. (got by PlatformUI.getWorkbench().getWorkbenchWindows()[0].getActivePage().findView(IDebugUIConstants.ID_EXPRESSION_VIEW);). Then it checks which items are currently visible (based on the method shown here: http://git.eclipse.org/c/platform/eclipse.platform.swt.git/tree/examples/org.eclipse.swt.snippets/src/org/eclipse/swt/snippets/Snippet358.java). The result of this is a 'range' of visible children of the expression that'll be updated. That range (e.g. 4...8) is stored within MIExpressionDMC (which has been extended by two members to store that range). In MIVariableManager.getVariable(...), that range is extracted from the MIExpressionDMC and forwarded to the MIRootVariableObject which in turn updates the 'frozen' state of its MIVariableObjects. They finally execute the GDB '-var-set-frozen' command if the frozen state changed.

The prototype seems to works and it CDT performs MUCH better with huge structs. Also, if a struct is collapsed, all it's member will become frozen and hence the '-var-update' executes in virtually no time. BUT I'm quite unhappy with the implementation. It feels more like a hack than a solutions to me and that makes me unsure how to proceed from here.

If desired, I could push this (ugly) prototype to Gerrit if that helps to get more information/tips from experts on how to proceed.

Raphael

On 08/14/2014 02:29 PM, Raphael Zulliger wrote:
On 08/14/2014 12:38 PM, Pascal Rapicault wrote:
On which criteria would the framework emit those commands?
Not quite sure on what your question focuses. But beside the question how to implement it, in the ideal world, CDT would behave like that (IMHO):

Assume we're in the Expression View, having two root items both of type class/struct and both contain some members, like this:

=======================================  (This is the view top border)
|   |_ MyObject             | {...}   |  (assume varobj name="var1")
|         |_  m_Member1| value 1 | (assume varobj name="var1.m_Member1")
|         |_  m_Member2     | value 2 |  ...
|         |_  m_Member3     | value 3 |
|         |_  m_Member4     | value 4 |
|   |_ MyOtherObject        | {...}   | (assume varobj name="var2")
| |_ m_Array1[20];| {...} | (assume varobj name="var2.m_Array1")
|         |_  m_OthrMember2 | value 2 |
|         |_  m_OthrMember3 | value 3 |
======================================= (This is the view bottom border)
|_ m_OthrMember5(invisible - therefore don't get value fromembedded target) |_ m_OthrMember6(invisible- therefore don't get value from embedded target) |_ m_OthrMember7(invisible- therefore don't get value from embedded target)
...


In that situation, there are more members than can be shown without scrolling down. Therefore, from "m_OthrMember4" (which is hidden below the bottom border) and further below, no more members are visible. Therefore, it is a waste of resources to refresh them, as CDT/GDB is doing it today. This especially hurts if a struct contains hundreds of members (e.g. a struct that represents hardware registers with hundreds or even thousands of members which can easily cumulate to a total size of 1MByte which happen to be refreshed on every debug event).Btw: this happens because CDT executes a '-var-update 1 var1' and '-var-update 1 var2' on every debugging event. And because CDT didn't freeze any members, GDB will just update all members, resulting in reading all the memory of the struct from the (embedded) target, e.g. 1MByte(!).

If you're question focus on the "how to notice when a member appears or disappears" from the visible range, e.g. because the user is scrolling and the like: Well, that's exactly what my initial post tries to find out.

Right now, as I'm writing this, I realize that CDT already does something like that. E.g. when initially expanding a struct (e.g. MyOtherObject), then CDT does only execute '-var-evaluate-expression' on the visible items (m_Array1, OthrMember2and m_OthrMember3in this example). Then, when I scroll down in the Expression View, so that m_OthrMember4 appears, CDT executes another "-var-evaluate-expression" for var2.m_OthrMember4, right when that member starts appearing. I might study that code to find out more...

Raphael


On 14/08/2014 10:52 AM, Raphael Zulliger wrote:
Hi

To increase debugging performance when having huge data structures in Variable/Expression View etc., I'd like to make extend CDT with GDB's "-var-set-frozen" or "-var-set-update-range" features (see https://sourceware.org/gdb/current/onlinedocs/gdb/GDB_002fMI-Variable-Objects.html).

I'm still quite unfamiliar with the ViewModel concept and how it finally links to the UI. Therefore, can someone point me towards a good starting point regarding: How can I know which elements in the Variable View, Expression View are currently visible? (i.e. if there are 1000 members in a struct, the view will at most show a few dozens, depending on the height of the view - all others are invisible). How could I get notified about changes (e.g. the user scrolls down the list)?

Any idea/hint would highly be appreciated!

Thanks,
Raphael


Back to the top