Skip to content

Commit 74e9edf

Browse files
committed
feat(vnext): prepare local relation evidence
1 parent 1dc15d8 commit 74e9edf

8 files changed

Lines changed: 1047 additions & 42 deletions

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
"test:browser": "vitest run --config vitest.browser.config.ts",
2727
"test:worker-placement": "node ./scripts/worker-placement.mjs",
2828
"test:integrity": "node ./scripts/check-test-integrity.mjs",
29+
"bench:local-relation-site": "vitest bench --run src/vnext/__tests__/local-relation-site.bench.ts",
2930
"bench:parser-adapter": "vitest bench --run src/vnext/__tests__/node-sql-parser-adapter.bench.ts",
3031
"bench:query-site": "vitest bench --run src/vnext/__tests__/query-site.bench.ts",
3132
"bench:statement-index": "vitest bench --run src/vnext/__tests__/statement-index.bench.ts",
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
import { bench, describe } from "vitest";
2+
import { MAX_CTE_DECLARATIONS } from "../cte-layout.js";
3+
import {
4+
analyzeSqlLocalRelationSite,
5+
prepareSqlLocalRelationStatement,
6+
type SqlLocalRelationStatement,
7+
} from "../local-relation-site.js";
8+
import { DUCKDB_SQL_RELATION_DIALECT } from "../relation-dialect.js";
9+
import { createIdentitySqlSource } from "../source.js";
10+
import {
11+
buildSqlStatementIndex,
12+
findSqlStatementSlot,
13+
} from "../statement-index.js";
14+
15+
interface Fixture {
16+
readonly index: ReturnType<typeof buildSqlStatementIndex>;
17+
readonly position: number;
18+
readonly slot: ReturnType<typeof findSqlStatementSlot>;
19+
readonly source: ReturnType<typeof createIdentitySqlSource>;
20+
readonly statement: SqlLocalRelationStatement;
21+
}
22+
23+
function fixture(text: string): Fixture {
24+
const source = createIdentitySqlSource(text);
25+
const index = buildSqlStatementIndex(
26+
source.analysisText,
27+
DUCKDB_SQL_RELATION_DIALECT.querySite.lexicalProfile,
28+
);
29+
const position = text.length;
30+
const slot = findSqlStatementSlot(index, position, "left");
31+
const preparation = prepareSqlLocalRelationStatement(
32+
source,
33+
index,
34+
slot,
35+
DUCKDB_SQL_RELATION_DIALECT,
36+
);
37+
if (preparation.status === "unavailable") {
38+
throw new Error("Local relation benchmark must prepare");
39+
}
40+
return {
41+
index,
42+
position,
43+
slot,
44+
source,
45+
statement: preparation.statement,
46+
};
47+
}
48+
49+
function coldAnalyze(value: Fixture) {
50+
const preparation = prepareSqlLocalRelationStatement(
51+
value.source,
52+
value.index,
53+
value.slot,
54+
DUCKDB_SQL_RELATION_DIALECT,
55+
);
56+
if (preparation.status === "unavailable") {
57+
throw new Error("Cold local relation benchmark must prepare");
58+
}
59+
return analyzeSqlLocalRelationSite(
60+
preparation.statement,
61+
value.position,
62+
);
63+
}
64+
65+
const tenKibibytes = 10 * 1_024;
66+
const withPrefix = "WITH local_cte AS (SELECT 1) SELECT ";
67+
const withSuffix = " FROM target";
68+
const projectionLength =
69+
tenKibibytes - withPrefix.length - withSuffix.length;
70+
const withText = `${withPrefix}${"x,".repeat(
71+
Math.floor((projectionLength - 1) / 2),
72+
)}x${withSuffix}`;
73+
const paddedWithText = `${withText.slice(
74+
0,
75+
-withSuffix.length,
76+
)}${" ".repeat(tenKibibytes - withText.length)}${withSuffix}`;
77+
if (paddedWithText.length !== tenKibibytes) {
78+
throw new Error("Local relation benchmark must be exactly 10 KiB");
79+
}
80+
const withFixture = fixture(paddedWithText);
81+
82+
const maximumCteText = `WITH ${Array.from(
83+
{ length: MAX_CTE_DECLARATIONS },
84+
(_, index) => `c${index} AS (SELECT ${index})`,
85+
).join(", ")} SELECT * FROM target`;
86+
const maximumCteFixture = fixture(maximumCteText);
87+
88+
const withPreflight = analyzeSqlLocalRelationSite(
89+
withFixture.statement,
90+
withFixture.position,
91+
);
92+
const maximumCtePreflight = analyzeSqlLocalRelationSite(
93+
maximumCteFixture.statement,
94+
maximumCteFixture.position,
95+
);
96+
if (
97+
withPreflight.status !== "ready" ||
98+
withPreflight.local.kind !== "unqualified" ||
99+
withPreflight.local.cteVisibility.ctes.length !== 1
100+
) {
101+
throw new Error("10 KiB benchmark must expose one visible CTE");
102+
}
103+
if (
104+
maximumCtePreflight.status !== "ready" ||
105+
maximumCtePreflight.local.kind !== "unqualified" ||
106+
maximumCtePreflight.local.cteVisibility.ctes.length !==
107+
MAX_CTE_DECLARATIONS
108+
) {
109+
throw new Error("Maximum benchmark must expose every CTE");
110+
}
111+
112+
describe("local relation site", () => {
113+
bench("cold 10 KiB WITH statement", () => {
114+
coldAnalyze(withFixture);
115+
});
116+
117+
bench("warm 10 KiB WITH statement", () => {
118+
analyzeSqlLocalRelationSite(
119+
withFixture.statement,
120+
withFixture.position,
121+
);
122+
});
123+
124+
bench("cold 256-CTE statement", () => {
125+
coldAnalyze(maximumCteFixture);
126+
});
127+
128+
bench("warm 256-CTE statement", () => {
129+
analyzeSqlLocalRelationSite(
130+
maximumCteFixture.statement,
131+
maximumCteFixture.position,
132+
);
133+
});
134+
});

0 commit comments

Comments
 (0)