Skip to content

Commit d37469f

Browse files
committed
Add 'per evaluation' option next to metric
1 parent 2cae71c commit d37469f

File tree

1 file changed

+60
-27
lines changed

1 file changed

+60
-27
lines changed

extensions/ql-vscode/src/view/compare-performance/ComparePerformance.tsx

Lines changed: 60 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -99,8 +99,15 @@ function renderOptionalValue(x: Optional<number>, unit?: string) {
9999
}
100100
}
101101

102-
function renderPredicateMetric(x: Optional<PredicateInfo>, metric: Metric) {
103-
return renderOptionalValue(metricGetOptional(metric, x), metric.unit);
102+
function renderPredicateMetric(
103+
x: Optional<PredicateInfo>,
104+
metric: Metric,
105+
isPerEvaluation: boolean,
106+
) {
107+
return renderOptionalValue(
108+
metricGetOptional(metric, x, isPerEvaluation),
109+
metric.unit,
110+
);
104111
}
105112

106113
function renderDelta(x: number, unit?: string) {
@@ -338,36 +345,34 @@ interface Metric {
338345

339346
const metrics: Record<string, Metric> = {
340347
tuples: {
341-
title: "Tuples in pipeline",
348+
title: "Tuple count",
342349
get: (info) => info.tuples,
343350
},
344351
time: {
345-
title: "Time spent (milliseconds)",
352+
title: "Time spent",
346353
get: (info) => info.timeCost,
347354
unit: "ms",
348355
},
349356
evaluations: {
350357
title: "Evaluations",
351358
get: (info) => info.evaluationCount,
352359
},
353-
iterations: {
354-
title: "Iterations (per evaluation)",
355-
get: (info) =>
356-
info.evaluationCount === 0
357-
? 0
358-
: info.iterationCount / info.evaluationCount,
359-
},
360360
iterationsTotal: {
361-
title: "Iterations (total)",
361+
title: "Iterations",
362362
get: (info) => info.iterationCount,
363363
},
364364
};
365365

366366
function metricGetOptional(
367367
metric: Metric,
368-
value: Optional<PredicateInfo>,
368+
info: Optional<PredicateInfo>,
369+
isPerEvaluation: boolean,
369370
): Optional<number> {
370-
return isPresent(value) ? metric.get(value) : value;
371+
if (!isPresent(info)) {
372+
return info;
373+
}
374+
const value = metric.get(info);
375+
return isPerEvaluation ? (value / info.evaluationCount) | 0 : value;
371376
}
372377

373378
function addOptionals(a: Optional<number>, b: Optional<number>) {
@@ -450,6 +455,8 @@ function ComparePerformanceWithData(props: {
450455

451456
const [metric, setMetric] = useState<Metric>(metrics.tuples);
452457

458+
const [isPerEvaluation, setPerEvaluation] = useState(false);
459+
453460
const nameSet = useMemo(
454461
() => union(from.data.names, to.data.names),
455462
[from, to],
@@ -463,8 +470,8 @@ function ComparePerformanceWithData(props: {
463470
.map((name) => {
464471
const before = from.getTupleCountInfo(name);
465472
const after = to.getTupleCountInfo(name);
466-
const beforeValue = metricGetOptional(metric, before);
467-
const afterValue = metricGetOptional(metric, after);
473+
const beforeValue = metricGetOptional(metric, before, isPerEvaluation);
474+
const afterValue = metricGetOptional(metric, after, isPerEvaluation);
468475
if (beforeValue === afterValue) {
469476
return undefined!;
470477
}
@@ -484,7 +491,7 @@ function ComparePerformanceWithData(props: {
484491
})
485492
.filter((x) => !!x)
486493
.sort(getSortOrder(sortOrder));
487-
}, [nameSet, from, to, metric, hideCacheHits, sortOrder]);
494+
}, [nameSet, from, to, metric, hideCacheHits, sortOrder, isPerEvaluation]);
488495

489496
const { totalBefore, totalAfter, totalDiff } = useMemo(() => {
490497
let totalBefore = 0;
@@ -519,10 +526,10 @@ function ComparePerformanceWithData(props: {
519526
return Array.from(groupedRows.entries())
520527
.map(([fingerprint, rows]) => {
521528
const before = rows
522-
.map((row) => metricGetOptional(metric, row.before))
529+
.map((row) => metricGetOptional(metric, row.before, isPerEvaluation))
523530
.reduce(addOptionals);
524531
const after = rows
525-
.map((row) => metricGetOptional(metric, row.after))
532+
.map((row) => metricGetOptional(metric, row.after, isPerEvaluation))
526533
.reduce(addOptionals);
527534
return {
528535
name: rows.length === 1 ? rows[0].name : fingerprint,
@@ -534,7 +541,7 @@ function ComparePerformanceWithData(props: {
534541
} satisfies RowGroup;
535542
})
536543
.sort(getSortOrder(sortOrder));
537-
}, [rows, metric, sortOrder, deferredRenamings]);
544+
}, [rows, metric, sortOrder, deferredRenamings, isPerEvaluation]);
538545

539546
const rowGroupNames = useMemo(
540547
() => abbreviateRANames(rowGroups.map((group) => group.name)),
@@ -576,6 +583,14 @@ function ComparePerformanceWithData(props: {
576583
</option>
577584
))}
578585
</Dropdown>{" "}
586+
<Dropdown
587+
onChange={(e: ChangeEvent<HTMLSelectElement>) =>
588+
setPerEvaluation(e.target.value === "per-evaluation")
589+
}
590+
>
591+
<option value="total">Overall</option>
592+
<option value="per-evaluation">Per evaluation</option>
593+
</Dropdown>{" "}
579594
sorted by{" "}
580595
<Dropdown
581596
onChange={(e: ChangeEvent<HTMLSelectElement>) =>
@@ -602,6 +617,7 @@ function ComparePerformanceWithData(props: {
602617
rowGroupNames={rowGroupNames}
603618
comparison={comparison}
604619
metric={metric}
620+
isPerEvaluation={isPerEvaluation}
605621
/>
606622
<Table>
607623
<tfoot>
@@ -628,17 +644,20 @@ interface PredicateTableProps {
628644
rowGroupNames: React.ReactNode[];
629645
comparison: boolean;
630646
metric: Metric;
647+
isPerEvaluation: boolean;
631648
}
632649

633650
function PredicateTableRaw(props: PredicateTableProps) {
634-
const { comparison, metric, rowGroupNames, rowGroups } = props;
651+
const { comparison, metric, rowGroupNames, rowGroups, isPerEvaluation } =
652+
props;
635653
return rowGroups.map((rowGroup, rowGroupIndex) => (
636654
<PredicateRowGroup
637655
key={rowGroupIndex}
638656
renderedName={rowGroupNames[rowGroupIndex]}
639657
rowGroup={rowGroup}
640658
comparison={comparison}
641659
metric={metric}
660+
isPerEvaluation={isPerEvaluation}
642661
/>
643662
));
644663
}
@@ -650,10 +669,11 @@ interface PredicateRowGroupProps {
650669
rowGroup: RowGroup;
651670
comparison: boolean;
652671
metric: Metric;
672+
isPerEvaluation: boolean;
653673
}
654674

655675
function PredicateRowGroup(props: PredicateRowGroupProps) {
656-
const { renderedName, rowGroup, comparison, metric } = props;
676+
const { renderedName, rowGroup, comparison, metric, isPerEvaluation } = props;
657677
const [isExpanded, setExpanded] = useState(false);
658678
const rowNames = useMemo(
659679
() => abbreviateRANames(rowGroup.rows.map((row) => row.name)),
@@ -689,6 +709,7 @@ function PredicateRowGroup(props: PredicateRowGroupProps) {
689709
row={row}
690710
comparison={comparison}
691711
metric={metric}
712+
isPerEvaluation={isPerEvaluation}
692713
/>
693714
</td>
694715
</tr>
@@ -703,11 +724,16 @@ interface PredicateRowProps {
703724
row: Row;
704725
comparison: boolean;
705726
metric: Metric;
727+
isPerEvaluation: boolean;
706728
}
707729

708730
function PredicateRow(props: PredicateRowProps) {
709731
const [isExpanded, setExpanded] = useState(false);
710-
const { renderedName, row, comparison, metric } = props;
732+
const { renderedName, row, comparison, metric, isPerEvaluation } = props;
733+
const evaluationFactorBefore =
734+
isPerEvaluation && isPresent(row.before) ? row.before.evaluationCount : 1;
735+
const evaluationFactorAfter =
736+
isPerEvaluation && isPresent(row.after) ? row.after.evaluationCount : 1;
711737
return (
712738
<Table className={isExpanded ? "expanded" : ""}>
713739
<tbody>
@@ -719,8 +745,9 @@ function PredicateRow(props: PredicateRowProps) {
719745
<ChevronCell>
720746
<Chevron expanded={isExpanded} />
721747
</ChevronCell>
722-
{comparison && renderPredicateMetric(row.before, metric)}
723-
{renderPredicateMetric(row.after, metric)}
748+
{comparison &&
749+
renderPredicateMetric(row.before, metric, isPerEvaluation)}
750+
{renderPredicateMetric(row.after, metric, isPerEvaluation)}
724751
{comparison && renderDelta(row.diff, metric.unit)}
725752
<NameCell>{renderedName}</NameCell>
726753
</PredicateTR>
@@ -761,8 +788,14 @@ function PredicateRow(props: PredicateRowProps) {
761788
(step, index) => (
762789
<PipelineStep
763790
key={index}
764-
before={first?.counts[index]}
765-
after={second?.counts[index]}
791+
before={
792+
first &&
793+
(first.counts[index] / evaluationFactorBefore) | 0
794+
}
795+
after={
796+
second &&
797+
(second.counts[index] / evaluationFactorAfter) | 0
798+
}
766799
comparison={comparison}
767800
step={step}
768801
/>

0 commit comments

Comments
 (0)