Skip to content

Add additional tables to Memory view for drilling down #14

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Sep 25, 2018

Conversation

DanTup
Copy link
Contributor

@DanTup DanTup commented Sep 19, 2018

@devoncarew This adds multiple tables to the Memory page that appear/disappear based on selection (hopefully this is what you were describing - see below).

Currently it has hard-coded data because I'm not sure how to get the data. I did wire it up to _getInstances in the VM then realised that it was supposed to be a snapshot (most things returned Sentinel fetching them live!).

I can see there's a _loadHeapSnapshot function but it's commented out, and it only seems to result in a byte array. Is there any info on how this works I can look at? And do we need to be concerned about it being fetched separately to _getAllocationProfile (su the results might not match perfectly)?

screen shot 2018-09-19 at 3 02 04 pm
screen shot 2018-09-19 at 3 02 10 pm
screen shot 2018-09-19 at 3 02 15 pm

@devoncarew
Copy link
Member

Yup, the UI looks great - let me look through the code.

@@ -293,6 +362,15 @@ class MemoryColumnInstanceCount extends Column<ClassHeapStats> {
String render(dynamic value) => Column.fastIntl(value);
}

class MemoryColumnSimple<T> extends Column<T> {
String Function(T) getter;
MemoryColumnSimple(String name, this.getter, {bool wide = false})
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't need to change now, but Flutter style is that constructors come first. I see that we're not consistent with that in this codebase, so in some future PR we should update the class definitions.

@devoncarew
Copy link
Member

And do we need to be concerned about it being fetched separately to _getAllocationProfile (as the results might not match perfectly)?

We can look at what the Observatory does here (https://github.com/dart-lang/sdk/blob/03d68355d6ff699bfc9df5b86f8b1f175bd4a88c/runtime/observatory/lib/src/service/object.dart#L1577); I would guess a snapshot in time is what we want. We can always wire that up separately from the UI.

For the UI, this is very similar to what I was thinking of. The deltas are that instead of a hard-coded list of tables expanding out to the right, we want the selection in the n-1 table to inform what kind of table to render to its right. So, selecting in the initial table would show a table of all the instances of a class. Selecting in that table would show a table with outbound references (the fields of that instance). Selecting in that one (an object) would show its outbound references to the right. You can then progressively explore the heap.

In that setup, I'd imagine the tables are mostly a fixed width, and that they're in a panel that where there are enough contents, will scroll horizontally.

@DanTup
Copy link
Contributor Author

DanTup commented Sep 20, 2018

Ok, I changed the tables over to a stack so we can push new tables based on the selected data:

devtools

I also added a spinner for async work, though it's possible it doesn't make sense anywhere except waiting for the snapshot (there may not be much async work elsewhere, and things like getObject are very fast).

I might look at the data stuff on another branch that targets this one to simplify the PRs/changesets a little.

Copy link
Member

@devoncarew devoncarew left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

A possible future change is to have a ViewManager class - it would handle the stack of Views that extend out to the right. A View subclass would know how in render itself (as a table), and would be provided with an input object - a class type, or an instance. It would listen to its own selection, and then tell the parent ViewManager to create a new child to its right - another View subclass.

In any case, not something for this PR, but more useful when we want to display more kinds of data.

tableContainer.element.scrollTo(<String, dynamic>{
'left': tableContainer.element.scrollWidth,
'top': 0,
'behavior': 'smooth'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: add a trailing comma?

@@ -102,8 +130,9 @@ class MemoryScreen extends Screen {
return stats.instancesCurrent > 0; //|| stats.instancesAccumulated > 0;
}).toList();

memoryTable.setRows(heapStats);
tableStack.first..setRows(heapStats);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

too many periods (first..setRows())

});

// Kick off population of data for the table.
// TODO: If it turns out not to be async work, remove the spinner.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO(dantup)

@@ -25,7 +26,10 @@ class MemoryScreen extends Screen {
StatusItem objectCountStatus;

PButton loadSnapshotButton;
Table<ClassHeapStats> memoryTable;

// TODO(dantup): Is it reasonable to put dynamic here?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Object may be more correct here - the common super class of all the things we could display.

@DanTup DanTup force-pushed the multiple-tables-for-memory branch from 5c1a975 to a7d90b0 Compare September 24, 2018 08:18
@DanTup
Copy link
Contributor Author

DanTup commented Sep 24, 2018

A possible future change is to have a ViewManager class

Sounds like a good idea. I think it may be easier to do with a second use of this (it'll be clearer which bits of the behaviour need to be controlled from the outside) so will tackle it then.

I've addressed the other comments, and moved constructors to the top for all the classes in this file (I didn't do the whole repo for fear of making lots of conflicts on outstanding PRs/unpushed changes!). Also rebased on master.

LMK if you're happy with this being merged while it still has fake data.

@devoncarew
Copy link
Member

LMK if you're happy with this being merged while it still has fake data.

Yes, sounds good. I think we'd still in the prototyping stage.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants