From 260bf0e8d1630b988f848ae35b980f83ba9cc512 Mon Sep 17 00:00:00 2001 From: Asger F Date: Thu, 14 Nov 2024 14:41:29 +0100 Subject: [PATCH] Add option to choose metric --- .../ComparePerformance.tsx | 87 ++++++++++++++++--- 1 file changed, 74 insertions(+), 13 deletions(-) diff --git a/extensions/ql-vscode/src/view/compare-performance/ComparePerformance.tsx b/extensions/ql-vscode/src/view/compare-performance/ComparePerformance.tsx index b566ec93a..3a236616b 100644 --- a/extensions/ql-vscode/src/view/compare-performance/ComparePerformance.tsx +++ b/extensions/ql-vscode/src/view/compare-performance/ComparePerformance.tsx @@ -28,6 +28,7 @@ interface OptionalValue { interface PredicateInfo extends OptionalValue { evaluationCount: number; iterationCount: number; + timeCost: number; pipelines: Record; } @@ -54,6 +55,7 @@ class ComparisonDataset { evaluationCount: 0, iterationCount: 0, tuples: 0, + timeCost: 0, absentReason: AbsentReason.NotSeen, pipelines: {}, }; @@ -70,6 +72,7 @@ class ComparisonDataset { return { evaluationCount: data.evaluationCounts[index], iterationCount: data.iterationCounts[index], + timeCost: data.timeCosts[index], tuples: tupleCost, absentReason, pipelines: data.pipelineSummaryList[index], @@ -77,7 +80,7 @@ class ComparisonDataset { } } -function renderAbsoluteValue(x: OptionalValue) { +function renderAbsoluteValue(x: PredicateInfo, metric: Metric) { switch (x.absentReason) { case AbsentReason.NotSeen: return n/a; @@ -86,20 +89,30 @@ function renderAbsoluteValue(x: OptionalValue) { case AbsentReason.Sentinel: return sentinel empty; default: - return {formatDecimal(x.tuples)}; + return ( + + {formatDecimal(metric.get(x))} + {renderUnit(metric.unit)} + + ); } } -function renderDelta(x: number) { +function renderDelta(x: number, unit?: string) { const sign = x > 0 ? "+" : ""; return ( 0 ? "bad-value" : x < 0 ? "good-value" : ""}> {sign} {formatDecimal(x)} + {renderUnit(unit)} ); } +function renderUnit(unit: string | undefined) { + return unit == null ? "" : ` ${unit}`; +} + function orderBy(fn: (x: T) => number | string) { return (x: T, y: T) => { const fx = fn(x); @@ -198,7 +211,7 @@ const PipelineStepTR = styled.tr` } `; -const SortOrderDropdown = styled.select``; +const Dropdown = styled.select``; interface PipelineStepProps { before: number | undefined; @@ -287,6 +300,37 @@ function getSortOrder(sortOrder: "delta" | "absDelta") { return orderBy((row: TRow) => row.diff); } +interface Metric { + title: string; + get(info: PredicateInfo): number; + unit?: string; +} + +const metrics: Record = { + tuples: { + title: "Tuples in pipeline", + get: (info) => info.tuples, + }, + time: { + title: "Time spent (milliseconds)", + get: (info) => info.timeCost, + unit: "ms", + }, + evaluations: { + title: "Evaluations", + get: (info) => info.evaluationCount, + }, + iterations: { + title: "Iterations (per evaluation)", + get: (info) => + info.absentReason ? 0 : info.iterationCount / info.evaluationCount, + }, + iterationsTotal: { + title: "Iterations (total)", + get: (info) => info.iterationCount, + }, +}; + function Chevron({ expanded }: { expanded: boolean }) { return ; } @@ -332,6 +376,8 @@ export function ComparePerformance(_: Record) { const [sortOrder, setSortOrder] = useState<"delta" | "absDelta">("absDelta"); + const [metric, setMetric] = useState(metrics.tuples); + if (!datasets) { return
Loading performance comparison...
; } @@ -349,7 +395,9 @@ export function ComparePerformance(_: Record) { .map((name) => { const before = from.getTupleCountInfo(name); const after = to.getTupleCountInfo(name); - if (before.tuples === after.tuples) { + const beforeValue = metric.get(before); + const afterValue = metric.get(after); + if (beforeValue === afterValue) { return undefined!; } if ( @@ -361,7 +409,7 @@ export function ComparePerformance(_: Record) { return undefined!; } } - const diff = after.tuples - before.tuples; + const diff = afterValue - beforeValue; return { name, before, after, diff }; }) .filter((x) => !!x) @@ -372,8 +420,8 @@ export function ComparePerformance(_: Record) { let totalDiff = 0; for (const row of rows) { - totalBefore += row.before.tuples; - totalAfter += row.after.tuples; + totalBefore += metric.get(row.before); + totalAfter += metric.get(row.after); totalDiff += row.diff; } @@ -401,7 +449,20 @@ export function ComparePerformance(_: Record) { )} - ) => + setMetric(metrics[e.target.value]) + } + > + {Object.entries(metrics).map(([key, value]) => ( + + ))} + {" "} + sorted by{" "} + ) => setSortOrder(e.target.value as "delta" | "absDelta") } @@ -409,7 +470,7 @@ export function ComparePerformance(_: Record) { > - + @@ -439,9 +500,9 @@ export function ComparePerformance(_: Record) { - {renderAbsoluteValue(row.before)} - {renderAbsoluteValue(row.after)} - {renderDelta(row.diff)} + {renderAbsoluteValue(row.before, metric)} + {renderAbsoluteValue(row.after, metric)} + {renderDelta(row.diff, metric.unit)} {rowNames[rowIndex]} {expandedPredicates.has(row.name) && (