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 {
evaluationCount: number;
iterationCount: number;
timeCost: number;
pipelines: Record<string, PipelineSummary>;
}
@@ -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 <AbsentNumberCell>n/a</AbsentNumberCell>;
@@ -86,20 +89,30 @@ function renderAbsoluteValue(x: OptionalValue) {
case AbsentReason.Sentinel:
return <AbsentNumberCell>sentinel empty</AbsentNumberCell>;
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 ? "+" : "";
return (
<NumberCell className={x > 0 ? "bad-value" : x < 0 ? "good-value" : ""}>
{sign}
{formatDecimal(x)}
{renderUnit(unit)}
</NumberCell>
);
}
function renderUnit(unit: string | undefined) {
return unit == null ? "" : ` ${unit}`;
}
function orderBy<T>(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<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 }) {
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 [metric, setMetric] = useState<Metric>(metrics.tuples);
if (!datasets) {
return <div>Loading performance comparison...</div>;
}
@@ -349,7 +395,9 @@ export function ComparePerformance(_: Record<string, never>) {
.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<string, never>) {
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<string, never>) {
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<string, never>) {
</label>
</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>) =>
setSortOrder(e.target.value as "delta" | "absDelta")
}
@@ -409,7 +470,7 @@ export function ComparePerformance(_: Record<string, never>) {
>
<option value="delta">Delta</option>
<option value="absDelta">Absolute delta</option>
</SortOrderDropdown>
</Dropdown>
<Table>
<thead>
<HeaderTR>
@@ -439,9 +500,9 @@ export function ComparePerformance(_: Record<string, never>) {
<ChevronCell>
<Chevron expanded={expandedPredicates.has(row.name)} />
</ChevronCell>
{renderAbsoluteValue(row.before)}
{renderAbsoluteValue(row.after)}
{renderDelta(row.diff)}
{renderAbsoluteValue(row.before, metric)}
{renderAbsoluteValue(row.after, metric)}
{renderDelta(row.diff, metric.unit)}
<NameCell>{rowNames[rowIndex]}</NameCell>
</PredicateTR>
{expandedPredicates.has(row.name) && (