vlsi / mat-calcite-plugin

Heap query plugin for Eclipse Memory Analyzer
Apache License 2.0
154 stars 24 forks source link

Enhancement: Allow multiple objects on selecting a GROUP BY result line. #7

Open ajohnson1 opened 6 years ago

ajohnson1 commented 6 years ago

MAT Calcite is a clever piece of software for enhancing Memory Analyzer.

I was looking at an old MAT defect and thought MAT Calcite might help. I'm not sure how to do inbounds() but GROUP BY and SUM work.

select length(a.this) as "length", count(a.this) as "count", sum(shallowSize(a.this)) as "total mem" from "java.lang.Object[]" a group by length order by "total mem" desc

Examining the result of that query gives a table. It would be really neat if with multiple objects associated per line MAT Calcite could return IContextObjectSet. That would allow the user to select a line or lines and operate on all the objects selected. See a standard histogram query for an example. Selecting a line lists the class in the inspector view, but the context menu operates on all the instance of the class. Perhaps getOQL() could return a Calcite SQL query returning just that particular line, though that might be tricky.

getResultMetaData could also be useful - this allows a list of ContextProviders via getContextProviders() and then a choice of results is presented for each line, as used for the ClassLoaderExplorer query where the choices are the class loader, or all the classes loaded by the loader. This could be used if there were multiple columns which could sensibly each return a IObject or set of objects.

vlsi commented 6 years ago

@ajohnson1 , glad you find MAT Calcite interesting.

I'm not sure how to do inbounds() but GROUP BY and SUM work.

Please check "table functions" in the README.

Here are samples from the unit tests as well: https://github.com/vlsi/mat-calcite-plugin/blob/master/MatCalciteTest/src/com/github/vlsi/mat/tests/calcite/BasicQueriesTests.java#L153-L165

Technically speaking, there's CARDINALITY(...) operator, so you can use either lateral (select * from table(getInboundReferences(hm.this))) or cross apply table(getInboundReferences(u.this)) or even select cardinality(getInboundReferences(hm.this)) ...

ajohnson1 commented 6 years ago

Okay, I think I have a way of solving the problem in the old MAT bug 241154:

select inb "#inbounds", count(arr.this) "#objects" from instanceof.java.lang.Object arr cross apply (select count(*) inb from table(getInboundReferences(arr.this)))  where length(arr.this) >= 0 group by inb order by inb asc

Notes:

My first attempts using cardinality() didn't work, hence the count(*) approach.

I see that you had already implemented my request for multiple context providers:

select * from java.util.HashMap shows

in the context menu. Thank you. On checking MAT doesn't do that for OQL - '*' displays a tree, not fields, but OQL select hm, hm.table from java.util.HashMap hm displays both columns, but not both as context menu items, so I have some work to do for OQL.

I'd still like to see multiple objects in a context menu for GROUP BY.

I'll continue to experiment with MAT Calcite to understand how to change OQL queries to SQL. I've also seen some exceptions in the MAT error log - once I can reproduce them I'll raise separate issues.

vlsi commented 6 years ago

On checking MAT doesn't do that for OQL - '*' displays a tree, not fields

I thought of displaying results as tree, however it is not clear how that should look like since columns might refer completely different objects in heap.

Do you have an idea there?