Skip to content
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

Add 'compare performance' view #3843

Open
wants to merge 37 commits into
base: main
Choose a base branch
from

Conversation

asgerf
Copy link
Contributor

@asgerf asgerf commented Nov 27, 2024

Adds the 'Compare Performance' UI from the hackathon.

Activate via right-clicking on a query history item

Screenshot 2024-11-27 at 14 37 31

Shows overview of predicate evaluation costs

Screenshot 2024-11-27 at 14 38 56

Click a predicate to show its pipeline(s) and tuple counts per step

Screenshot 2024-11-27 at 14 37 11

Changes since the hackathon:

  • The integration with DCA has been left out for now. I'm hoping @esbena will follow up on this.
  • Added support for predicate-renaming, which was WIP and not demoable in time for the Hackathon demo.
  • Some UI performance improvements: using useMemo and moved some state into subcomponents where a state change cause as much re-rendering.
  • Some clean up of the commit history; mainly squashing simple bugfixes into an earlier commit.

Despite my attempts at cleaning the commit history, it might actually be easiest to review as one giant diff.

asgerf and others added 30 commits November 27, 2024 13:47
Adds a dropdown with (at present) two options: sorting by delta and
sorting by absolute delta.
This ensures we can use hooks after the check in the main component
A very hacky implementation that simply instantiates an empty
`PerformanceOverviewScanner` as the "from" column (i.e. with all values
empty). To see it in action, select a single query run in the query
history and pick "Compare Performance" from the context menu. Then
select the "Single run" option when prompted.
Only contains formatting changes
Predicate names can't be empty, but it can happen with the renaming feature added in the next commit.
@asgerf asgerf force-pushed the asgerf/compare-perf-view branch 2 times, most recently from 13e78a6 to ec223fa Compare November 27, 2024 13:00
@asgerf asgerf force-pushed the asgerf/compare-perf-view branch from ec223fa to aa528c6 Compare November 27, 2024 13:14
@asgerf asgerf marked this pull request as ready for review November 27, 2024 13:41
@asgerf asgerf requested a review from a team as a code owner November 27, 2024 13:41
Copy link
Contributor

@aeisenberg aeisenberg left a comment

Choose a reason for hiding this comment

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

It looks ok to me in general. I haven't tried running this. It also seems isolated, so that if there is a problem, it is unlikely to affect other features.

There are a few questions and comments inside. Mostly, I'd like to either remove all TODOs and XXXs and replace them with a simple comment. If you think you will go back later to fix them, then please create an issue to track it.

{
"command": "codeQLQueryHistory.comparePerformanceWith",
"group": "3_queryHistory@1",
"when": "viewItem == rawResultsItem || viewItem == interpretedResultsItem"
Copy link
Contributor

Choose a reason for hiding this comment

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

Should this be limited to canary users? Probably.

Suggested change
"when": "viewItem == rawResultsItem || viewItem == interpretedResultsItem"
"when": "viewItem == rawResultsItem && config.codeQL.canary || viewItem == interpretedResultsItem && config.codeQL.canary"

};
}

protected onPanelDispose(): void {}
Copy link
Contributor

Choose a reason for hiding this comment

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

Do you want to remove references to resultsView and labelProvider?

Suggested change
protected onPanelDispose(): void {}
protected onPanelDispose(): void {
this.resultsView = null;
this.labelProvider = null;
}

Copy link
Contributor

Choose a reason for hiding this comment

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

Hmmm...not sure what the lifecycle of the view is. Is there a single view instance created for the entire extension, or is it one view per window that's opened?

progress?: ProgressCallback,
): Promise<T> {
progress?.({
// XXX all scans have step 1 - the backing progress tracker allows increments instead of steps - but for now we are happy with a tiny UI that says what is happening
Copy link
Contributor

Choose a reason for hiding this comment

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

I prefer avoiding XXX or TODOs in code that we're probably not going to get to.

Suggested change
// XXX all scans have step 1 - the backing progress tracker allows increments instead of steps - but for now we are happy with a tiny UI that says what is happening
// all scans have step 1 - the backing progress tracker allows increments instead of steps - but for now we are happy with a tiny UI that says what is happening

*/
export interface PerformanceComparisonDataFromLog {
/** Names of predicates mentioned in the log */
names: string[];
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we expect the lengths of these arrays to be the same for all? If not, which ones will have different sizes?

/**
* List of indices into the `names` array for which we have seen a cache hit.
*
* TODO: only count cache hits prior to first evaluation?
Copy link
Contributor

Choose a reason for hiding this comment

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

Here and below, if the TODO is tracked in an issue, can you add the issue? If it's not tracked, can you remove the TODO?

singleItem: QueryHistoryInfo,
multiSelect: QueryHistoryInfo[] | undefined,
) {
// TODO: reduce duplication with 'handleCompareWith'
Copy link
Contributor

Choose a reason for hiding this comment

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

Same...and below.

multiSelect: QueryHistoryInfo[] | undefined,
) {
// TODO: reduce duplication with 'handleCompareWith'
multiSelect ||= [singleItem];
Copy link
Contributor

Choose a reason for hiding this comment

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

That's a nice shortcut. I hadn't thought of that.

? allSelectedItems[1]
: allSelectedItems[0];
if (otherItem.databaseName !== dbName) {
throw new Error("Query databases must be the same.");
Copy link
Contributor

Choose a reason for hiding this comment

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

Minor: can you include the db names in this message?

args.push(parseQName());
skipToken(",");
}
args.reverse();
Copy link
Contributor

Choose a reason for hiding this comment

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

Why the reverse?

Comment on lines +139 to +142
if (prefix != null) {
result.push(prefix.abbreviate());
result.push("::");
}
Copy link
Contributor

Choose a reason for hiding this comment

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

This is quite complex to me. It is combining prefix from the closure with result, a local variable. This function is complex enough that maybe VisitResult should be a class and prefix is passed in as a private field. Then this function can become a member of VisitResult.

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.

4 participants