Add option to choose metric

This commit is contained in:
Asger F
2024-11-14 14:41:29 +01:00
parent 876c5b6091
commit 260bf0e8d1

View File

@@ -28,6 +28,7 @@ interface OptionalValue {
interface PredicateInfo extends OptionalValue { interface PredicateInfo extends OptionalValue {
evaluationCount: number; evaluationCount: number;
iterationCount: number; iterationCount: number;
timeCost: number;
pipelines: Record<string, PipelineSummary>; pipelines: Record<string, PipelineSummary>;
} }
@@ -54,6 +55,7 @@ class ComparisonDataset {
evaluationCount: 0, evaluationCount: 0,
iterationCount: 0, iterationCount: 0,
tuples: 0, tuples: 0,
timeCost: 0,
absentReason: AbsentReason.NotSeen, absentReason: AbsentReason.NotSeen,
pipelines: {}, pipelines: {},
}; };
@@ -70,6 +72,7 @@ class ComparisonDataset {
return { return {
evaluationCount: data.evaluationCounts[index], evaluationCount: data.evaluationCounts[index],
iterationCount: data.iterationCounts[index], iterationCount: data.iterationCounts[index],
timeCost: data.timeCosts[index],
tuples: tupleCost, tuples: tupleCost,
absentReason, absentReason,
pipelines: data.pipelineSummaryList[index], pipelines: data.pipelineSummaryList[index],
@@ -77,7 +80,7 @@ class ComparisonDataset {
} }
} }
function renderAbsoluteValue(x: OptionalValue) { function renderAbsoluteValue(x: PredicateInfo, metric: Metric) {
switch (x.absentReason) { switch (x.absentReason) {
case AbsentReason.NotSeen: case AbsentReason.NotSeen:
return <AbsentNumberCell>n/a</AbsentNumberCell>; return <AbsentNumberCell>n/a</AbsentNumberCell>;
@@ -86,20 +89,30 @@ function renderAbsoluteValue(x: OptionalValue) {
case AbsentReason.Sentinel: case AbsentReason.Sentinel:
return <AbsentNumberCell>sentinel empty</AbsentNumberCell>; return <AbsentNumberCell>sentinel empty</AbsentNumberCell>;
default: default:
return <NumberCell>{formatDecimal(x.tuples)}</NumberCell>; return (
<NumberCell>
{formatDecimal(metric.get(x))}
{renderUnit(metric.unit)}
</NumberCell>
);
} }
} }
function renderDelta(x: number) { function renderDelta(x: number, unit?: string) {
const sign = x > 0 ? "+" : ""; const sign = x > 0 ? "+" : "";
return ( return (
<NumberCell className={x > 0 ? "bad-value" : x < 0 ? "good-value" : ""}> <NumberCell className={x > 0 ? "bad-value" : x < 0 ? "good-value" : ""}>
{sign} {sign}
{formatDecimal(x)} {formatDecimal(x)}
{renderUnit(unit)}
</NumberCell> </NumberCell>
); );
} }
function renderUnit(unit: string | undefined) {
return unit == null ? "" : ` ${unit}`;
}
function orderBy<T>(fn: (x: T) => number | string) { function orderBy<T>(fn: (x: T) => number | string) {
return (x: T, y: T) => { return (x: T, y: T) => {
const fx = fn(x); const fx = fn(x);
@@ -198,7 +211,7 @@ const PipelineStepTR = styled.tr`
} }
`; `;
const SortOrderDropdown = styled.select``; const Dropdown = styled.select``;
interface PipelineStepProps { interface PipelineStepProps {
before: number | undefined; before: number | undefined;
@@ -287,6 +300,37 @@ function getSortOrder(sortOrder: "delta" | "absDelta") {
return orderBy((row: TRow) => row.diff); return orderBy((row: TRow) => row.diff);
} }
interface Metric {
title: string;
get(info: PredicateInfo): number;
unit?: string;
}
const metrics: Record<string, Metric> = {
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 }) { function Chevron({ expanded }: { expanded: boolean }) {
return <Codicon name={expanded ? "chevron-down" : "chevron-right"} />; return <Codicon name={expanded ? "chevron-down" : "chevron-right"} />;
} }
@@ -332,6 +376,8 @@ export function ComparePerformance(_: Record<string, never>) {
const [sortOrder, setSortOrder] = useState<"delta" | "absDelta">("absDelta"); const [sortOrder, setSortOrder] = useState<"delta" | "absDelta">("absDelta");
const [metric, setMetric] = useState<Metric>(metrics.tuples);
if (!datasets) { if (!datasets) {
return <div>Loading performance comparison...</div>; return <div>Loading performance comparison...</div>;
} }
@@ -349,7 +395,9 @@ export function ComparePerformance(_: Record<string, never>) {
.map((name) => { .map((name) => {
const before = from.getTupleCountInfo(name); const before = from.getTupleCountInfo(name);
const after = to.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!; return undefined!;
} }
if ( if (
@@ -361,7 +409,7 @@ export function ComparePerformance(_: Record<string, never>) {
return undefined!; return undefined!;
} }
} }
const diff = after.tuples - before.tuples; const diff = afterValue - beforeValue;
return { name, before, after, diff }; return { name, before, after, diff };
}) })
.filter((x) => !!x) .filter((x) => !!x)
@@ -372,8 +420,8 @@ export function ComparePerformance(_: Record<string, never>) {
let totalDiff = 0; let totalDiff = 0;
for (const row of rows) { for (const row of rows) {
totalBefore += row.before.tuples; totalBefore += metric.get(row.before);
totalAfter += row.after.tuples; totalAfter += metric.get(row.after);
totalDiff += row.diff; totalDiff += row.diff;
} }
@@ -401,7 +449,20 @@ export function ComparePerformance(_: Record<string, never>) {
</label> </label>
</WarningBox> </WarningBox>
)} )}
<SortOrderDropdown Compare{" "}
<Dropdown
onChange={(e: ChangeEvent<HTMLSelectElement>) =>
setMetric(metrics[e.target.value])
}
>
{Object.entries(metrics).map(([key, value]) => (
<option key={key} value={key}>
{value.title}
</option>
))}
</Dropdown>{" "}
sorted by{" "}
<Dropdown
onChange={(e: ChangeEvent<HTMLSelectElement>) => onChange={(e: ChangeEvent<HTMLSelectElement>) =>
setSortOrder(e.target.value as "delta" | "absDelta") setSortOrder(e.target.value as "delta" | "absDelta")
} }
@@ -409,7 +470,7 @@ export function ComparePerformance(_: Record<string, never>) {
> >
<option value="delta">Delta</option> <option value="delta">Delta</option>
<option value="absDelta">Absolute delta</option> <option value="absDelta">Absolute delta</option>
</SortOrderDropdown> </Dropdown>
<Table> <Table>
<thead> <thead>
<HeaderTR> <HeaderTR>
@@ -439,9 +500,9 @@ export function ComparePerformance(_: Record<string, never>) {
<ChevronCell> <ChevronCell>
<Chevron expanded={expandedPredicates.has(row.name)} /> <Chevron expanded={expandedPredicates.has(row.name)} />
</ChevronCell> </ChevronCell>
{renderAbsoluteValue(row.before)} {renderAbsoluteValue(row.before, metric)}
{renderAbsoluteValue(row.after)} {renderAbsoluteValue(row.after, metric)}
{renderDelta(row.diff)} {renderDelta(row.diff, metric.unit)}
<NameCell>{rowNames[rowIndex]}</NameCell> <NameCell>{rowNames[rowIndex]}</NameCell>
</PredicateTR> </PredicateTR>
{expandedPredicates.has(row.name) && ( {expandedPredicates.has(row.name) && (