Skip to content

Commit 2865f3b

Browse files
[Autoloop: perf-comparison] Iteration 405: readSqlQuery/toSql benchmark (N=10k, 20 iters)
Run: https://github.com/githubnext/tsb/actions/runs/29547282141 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 296e294 commit 2865f3b

2 files changed

Lines changed: 138 additions & 0 deletions

File tree

benchmarks/pandas/bench_sql.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
"""Benchmark: read_sql / to_sql on 10k-row DataFrames using SQLite in-memory"""
2+
import json
3+
import time
4+
import math
5+
import sqlite3
6+
import pandas as pd
7+
8+
ROWS = 10_000
9+
WARMUP = 3
10+
ITERATIONS = 20
11+
12+
# ── Build a matching dataset ──────────────────────────────────────────────────
13+
data = {
14+
"id": list(range(ROWS)),
15+
"value": [math.sin(i * 0.01) * 1000 for i in range(ROWS)],
16+
"label": [f"item_{i % 100}" for i in range(ROWS)],
17+
}
18+
df = pd.DataFrame(data)
19+
20+
# ── SQLite in-memory database ─────────────────────────────────────────────────
21+
con = sqlite3.connect(":memory:")
22+
df.to_sql("mock_table", con, index=False, if_exists="replace")
23+
24+
# ── Warm-up reads ─────────────────────────────────────────────────────────────
25+
for _ in range(WARMUP):
26+
pd.read_sql_query("SELECT * FROM mock_table", con)
27+
28+
# ── read_sql_query benchmark ──────────────────────────────────────────────────
29+
start_read = time.perf_counter()
30+
for _ in range(ITERATIONS):
31+
pd.read_sql_query("SELECT * FROM mock_table", con)
32+
total_read = (time.perf_counter() - start_read) * 1000
33+
34+
# ── Warm-up writes ────────────────────────────────────────────────────────────
35+
for _ in range(WARMUP):
36+
df.to_sql("bench_table", con, index=False, if_exists="replace")
37+
38+
# ── to_sql benchmark ──────────────────────────────────────────────────────────
39+
start_write = time.perf_counter()
40+
for _ in range(ITERATIONS):
41+
df.to_sql("bench_table", con, index=False, if_exists="replace")
42+
total_write = (time.perf_counter() - start_write) * 1000
43+
44+
con.close()
45+
46+
print(json.dumps({
47+
"function": "sql",
48+
"mean_ms": (total_read + total_write) / (2 * ITERATIONS),
49+
"iterations": ITERATIONS,
50+
"total_ms": total_read + total_write,
51+
"read_mean_ms": total_read / ITERATIONS,
52+
"write_mean_ms": total_write / ITERATIONS,
53+
}))

benchmarks/tsb/bench_sql.ts

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
/**
2+
* Benchmark: readSqlQuery / toSql on 10k-row result sets
3+
*/
4+
import { DataFrame, readSqlQuery, toSql } from "../../src/index.js";
5+
import type { SqlConnection, SqlResult, SqlRow, SqlValue, IfExistsStrategy } from "../../src/index.js";
6+
7+
const ROWS = 10_000;
8+
const WARMUP = 3;
9+
const ITERATIONS = 20;
10+
11+
// ── Shared result set ─────────────────────────────────────────────────────────
12+
const columns: string[] = ["id", "value", "label"];
13+
const rows: SqlRow[] = Array.from({ length: ROWS }, (_, i) => ({
14+
id: i,
15+
value: Math.sin(i * 0.01) * 1000,
16+
label: `item_${i % 100}`,
17+
}));
18+
19+
// ── Mock adapter for reads ────────────────────────────────────────────────────
20+
class ReadAdapter implements SqlConnection {
21+
query(_sql: string, _params?: readonly SqlValue[]): SqlResult {
22+
return { columns, rows };
23+
}
24+
listTables(): readonly string[] {
25+
return ["mock_table"];
26+
}
27+
}
28+
29+
const readConn = new ReadAdapter();
30+
31+
// ── Warm-up reads ─────────────────────────────────────────────────────────────
32+
for (let i = 0; i < WARMUP; i++) {
33+
readSqlQuery("SELECT * FROM mock_table", readConn);
34+
}
35+
36+
// ── readSqlQuery benchmark ────────────────────────────────────────────────────
37+
const startRead = performance.now();
38+
for (let i = 0; i < ITERATIONS; i++) {
39+
readSqlQuery("SELECT * FROM mock_table", readConn);
40+
}
41+
const totalRead = performance.now() - startRead;
42+
43+
// ── Mock adapter for writes ───────────────────────────────────────────────────
44+
class WriteAdapter implements SqlConnection {
45+
query(_sql: string, _params?: readonly SqlValue[]): SqlResult {
46+
return { columns: [], rows: [] };
47+
}
48+
listTables(): readonly string[] {
49+
return [];
50+
}
51+
insert(
52+
_tableName: string,
53+
_rows: readonly SqlRow[],
54+
_columns: readonly string[],
55+
_ifExists: IfExistsStrategy,
56+
): number {
57+
return _rows.length;
58+
}
59+
}
60+
61+
const writeConn = new WriteAdapter();
62+
const df = readSqlQuery("SELECT * FROM mock_table", readConn);
63+
64+
// ── Warm-up writes ────────────────────────────────────────────────────────────
65+
for (let i = 0; i < WARMUP; i++) {
66+
toSql(df, "bench_table", writeConn, { ifExists: "replace" });
67+
}
68+
69+
// ── toSql benchmark ───────────────────────────────────────────────────────────
70+
const startWrite = performance.now();
71+
for (let i = 0; i < ITERATIONS; i++) {
72+
toSql(df, "bench_table", writeConn, { ifExists: "replace" });
73+
}
74+
const totalWrite = performance.now() - startWrite;
75+
76+
console.log(
77+
JSON.stringify({
78+
function: "sql",
79+
mean_ms: (totalRead + totalWrite) / (2 * ITERATIONS),
80+
iterations: ITERATIONS,
81+
total_ms: totalRead + totalWrite,
82+
read_mean_ms: totalRead / ITERATIONS,
83+
write_mean_ms: totalWrite / ITERATIONS,
84+
}),
85+
);

0 commit comments

Comments
 (0)