Skip to content

Commit 46714bd

Browse files
Iteration 188: 6 new benchmark pairs (540 total, +1 vs best 539)
Add standalone function benchmarks: shiftSeries, isin (Series), astype (DataFrame), combineFirstSeries, toNumeric generic dispatcher, and pivot standalone. Run: https://github.com/githubnext/tsessebe/actions/runs/24604427165 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent d9b3dbf commit 46714bd

12 files changed

Lines changed: 404 additions & 0 deletions
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
"""Benchmark: astype standalone — DataFrame.astype with per-column and uniform dtype on 100k-row DataFrame."""
2+
import json, time
3+
import pandas as pd
4+
import numpy as np
5+
6+
SIZE = 100_000
7+
WARMUP = 5
8+
ITERATIONS = 50
9+
10+
df = pd.DataFrame({
11+
"a": np.arange(SIZE, dtype=np.float64),
12+
"b": np.arange(SIZE, dtype=np.int64),
13+
"c": np.where(np.arange(SIZE) % 2 == 0, 1, 0).astype(np.int64),
14+
})
15+
16+
for _ in range(WARMUP):
17+
df.astype({"a": "float32", "b": "int32"})
18+
df.astype("float64")
19+
20+
start = time.perf_counter()
21+
for _ in range(ITERATIONS):
22+
df.astype({"a": "float32", "b": "int32"})
23+
df.astype("float64")
24+
total = (time.perf_counter() - start) * 1000
25+
26+
print(json.dumps({
27+
"function": "astype_df_fn",
28+
"mean_ms": round(total / ITERATIONS, 3),
29+
"iterations": ITERATIONS,
30+
"total_ms": round(total, 3),
31+
}))
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
"""Benchmark: combineFirstSeries standalone — pd.Series.combine_first() on 50k-element Series with 30% NaN."""
2+
import json, time
3+
import pandas as pd
4+
import numpy as np
5+
6+
SIZE = 50_000
7+
WARMUP = 5
8+
ITERATIONS = 30
9+
10+
rng = np.random.default_rng(42)
11+
data1 = rng.standard_normal(SIZE)
12+
data1[::3] = float("nan") # ~30% nulls
13+
s1 = pd.Series(data1)
14+
s2 = pd.Series(np.arange(SIZE, dtype=np.float64) * 2.0)
15+
16+
for _ in range(WARMUP):
17+
s1.combine_first(s2)
18+
19+
start = time.perf_counter()
20+
for _ in range(ITERATIONS):
21+
s1.combine_first(s2)
22+
total = (time.perf_counter() - start) * 1000
23+
24+
print(json.dumps({
25+
"function": "combine_first_fn",
26+
"mean_ms": round(total / ITERATIONS, 3),
27+
"iterations": ITERATIONS,
28+
"total_ms": round(total, 3),
29+
}))
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
"""Benchmark: isin standalone — pd.Series.isin with large and small value sets on 100k-element Series."""
2+
import json, time
3+
import pandas as pd
4+
5+
SIZE = 100_000
6+
WARMUP = 5
7+
ITERATIONS = 50
8+
9+
s = pd.Series([i % 5000 for i in range(SIZE)])
10+
test_set = list(range(2500))
11+
test_set2 = [100, 200, 300, 400, 500]
12+
13+
for _ in range(WARMUP):
14+
s.isin(test_set)
15+
s.isin(test_set2)
16+
17+
start = time.perf_counter()
18+
for _ in range(ITERATIONS):
19+
s.isin(test_set)
20+
s.isin(test_set2)
21+
total = (time.perf_counter() - start) * 1000
22+
23+
print(json.dumps({
24+
"function": "isin_series_fn",
25+
"mean_ms": round(total / ITERATIONS, 3),
26+
"iterations": ITERATIONS,
27+
"total_ms": round(total, 3),
28+
}))
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
"""Benchmark: pivot standalone — pd.pivot() standalone function on a 100×20 grid DataFrame."""
2+
import json, time
3+
import pandas as pd
4+
import numpy as np
5+
6+
ROWS = 100
7+
COLS = 20
8+
WARMUP = 5
9+
ITERATIONS = 50
10+
11+
row_arr = []
12+
col_arr = []
13+
val_arr = []
14+
for r in range(ROWS):
15+
for c in range(COLS):
16+
row_arr.append(r)
17+
col_arr.append(c)
18+
val_arr.append(r * COLS + c + 0.5)
19+
20+
df = pd.DataFrame({"row": row_arr, "col": col_arr, "val": val_arr})
21+
22+
for _ in range(WARMUP):
23+
pd.pivot(df, index="row", columns="col", values="val")
24+
25+
start = time.perf_counter()
26+
for _ in range(ITERATIONS):
27+
pd.pivot(df, index="row", columns="col", values="val")
28+
total = (time.perf_counter() - start) * 1000
29+
30+
print(json.dumps({
31+
"function": "pivot_fn",
32+
"mean_ms": round(total / ITERATIONS, 3),
33+
"iterations": ITERATIONS,
34+
"total_ms": round(total, 3),
35+
}))
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
"""Benchmark: shiftSeries (standalone) — shift values by 1/−2/5 positions in a 100k-element Series."""
2+
import json, time
3+
import pandas as pd
4+
import numpy as np
5+
6+
SIZE = 100_000
7+
WARMUP = 5
8+
ITERATIONS = 50
9+
10+
s = pd.Series(np.arange(SIZE, dtype=np.float64))
11+
12+
for _ in range(WARMUP):
13+
s.shift(1)
14+
s.shift(-2)
15+
s.shift(5)
16+
17+
start = time.perf_counter()
18+
for _ in range(ITERATIONS):
19+
s.shift(1)
20+
s.shift(-2)
21+
s.shift(5)
22+
total = (time.perf_counter() - start) * 1000
23+
24+
print(json.dumps({
25+
"function": "shift_series_fn",
26+
"mean_ms": round(total / ITERATIONS, 3),
27+
"iterations": ITERATIONS,
28+
"total_ms": round(total, 3),
29+
}))
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
"""Benchmark: toNumeric generic — pd.to_numeric() with array, Series, and scalar inputs."""
2+
import json, time
3+
import pandas as pd
4+
5+
SIZE = 50_000
6+
WARMUP = 5
7+
ITERATIONS = 30
8+
9+
str_nums = [str(i * 1.5) for i in range(SIZE)]
10+
s = pd.Series(str_nums)
11+
12+
for _ in range(WARMUP):
13+
pd.to_numeric(str_nums, errors="coerce")
14+
pd.to_numeric(s, errors="coerce")
15+
pd.to_numeric("42.7")
16+
17+
start = time.perf_counter()
18+
for _ in range(ITERATIONS):
19+
pd.to_numeric(str_nums, errors="coerce")
20+
pd.to_numeric(s, errors="coerce")
21+
pd.to_numeric("42.7")
22+
total = (time.perf_counter() - start) * 1000
23+
24+
print(json.dumps({
25+
"function": "to_numeric_dispatch",
26+
"mean_ms": round(total / ITERATIONS, 3),
27+
"iterations": ITERATIONS,
28+
"total_ms": round(total, 3),
29+
}))
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/**
2+
* Benchmark: astype (standalone DataFrame) — exported astype(df, dtype) function on 100k-row DataFrame.
3+
* Mirrors pandas DataFrame.astype() called via standalone function.
4+
* Outputs JSON: {"function": "astype_df_fn", "mean_ms": ..., "iterations": ..., "total_ms": ...}
5+
*/
6+
import { DataFrame, astype } from "../../src/index.ts";
7+
8+
const SIZE = 100_000;
9+
const WARMUP = 5;
10+
const ITERATIONS = 50;
11+
12+
const df = new DataFrame({
13+
a: Array.from({ length: SIZE }, (_, i) => i * 1.0),
14+
b: Array.from({ length: SIZE }, (_, i) => i),
15+
c: Array.from({ length: SIZE }, (_, i) => (i % 2 === 0 ? 1 : 0)),
16+
});
17+
18+
for (let i = 0; i < WARMUP; i++) {
19+
astype(df, { a: "float32", b: "int32" });
20+
astype(df, "float64");
21+
}
22+
23+
const start = performance.now();
24+
for (let i = 0; i < ITERATIONS; i++) {
25+
astype(df, { a: "float32", b: "int32" });
26+
astype(df, "float64");
27+
}
28+
const total = performance.now() - start;
29+
30+
console.log(
31+
JSON.stringify({
32+
function: "astype_df_fn",
33+
mean_ms: Math.round((total / ITERATIONS) * 1000) / 1000,
34+
iterations: ITERATIONS,
35+
total_ms: Math.round(total * 1000) / 1000,
36+
}),
37+
);
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/**
2+
* Benchmark: combineFirstSeries standalone — exported combineFirstSeries(s1, s2) function.
3+
* Mirrors pandas Series.combine_first().
4+
* Outputs JSON: {"function": "combine_first_fn", "mean_ms": ..., "iterations": ..., "total_ms": ...}
5+
*/
6+
import { Series, combineFirstSeries } from "../../src/index.ts";
7+
8+
const SIZE = 50_000;
9+
const WARMUP = 5;
10+
const ITERATIONS = 30;
11+
12+
// s1: 50k elements with ~30% nulls
13+
const data1 = Array.from({ length: SIZE }, (_, i) => (i % 3 === 0 ? null : i * 1.5));
14+
// s2: 50k elements, fills in the nulls
15+
const data2 = Array.from({ length: SIZE }, (_, i) => i * 2.0);
16+
17+
const s1 = new Series({ data: data1 });
18+
const s2 = new Series({ data: data2 });
19+
20+
for (let i = 0; i < WARMUP; i++) {
21+
combineFirstSeries(s1, s2);
22+
}
23+
24+
const start = performance.now();
25+
for (let i = 0; i < ITERATIONS; i++) {
26+
combineFirstSeries(s1, s2);
27+
}
28+
const total = performance.now() - start;
29+
30+
console.log(
31+
JSON.stringify({
32+
function: "combine_first_fn",
33+
mean_ms: Math.round((total / ITERATIONS) * 1000) / 1000,
34+
iterations: ITERATIONS,
35+
total_ms: Math.round(total * 1000) / 1000,
36+
}),
37+
);
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/**
2+
* Benchmark: isin standalone — exported isin(series, values) function on 100k-element Series.
3+
* Mirrors pandas Series.isin() called as a standalone function.
4+
* Outputs JSON: {"function": "isin_series_fn", "mean_ms": ..., "iterations": ..., "total_ms": ...}
5+
*/
6+
import { Series, isin } from "../../src/index.ts";
7+
8+
const SIZE = 100_000;
9+
const WARMUP = 5;
10+
const ITERATIONS = 50;
11+
12+
const s = new Series({ data: Array.from({ length: SIZE }, (_, i) => i % 5000) });
13+
const testSet = Array.from({ length: 2500 }, (_, i) => i);
14+
const testSet2 = [100, 200, 300, 400, 500];
15+
16+
for (let i = 0; i < WARMUP; i++) {
17+
isin(s, testSet);
18+
isin(s, testSet2);
19+
}
20+
21+
const start = performance.now();
22+
for (let i = 0; i < ITERATIONS; i++) {
23+
isin(s, testSet);
24+
isin(s, testSet2);
25+
}
26+
const total = performance.now() - start;
27+
28+
console.log(
29+
JSON.stringify({
30+
function: "isin_series_fn",
31+
mean_ms: Math.round((total / ITERATIONS) * 1000) / 1000,
32+
iterations: ITERATIONS,
33+
total_ms: Math.round(total * 1000) / 1000,
34+
}),
35+
);

benchmarks/tsb/bench_pivot_fn.ts

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/**
2+
* Benchmark: pivot standalone — exported pivot(df, options) function on a DataFrame.
3+
* Mirrors pandas pd.pivot() standalone function.
4+
* Outputs JSON: {"function": "pivot_fn", "mean_ms": ..., "iterations": ..., "total_ms": ...}
5+
*/
6+
import { DataFrame, pivot } from "../../src/index.ts";
7+
8+
const ROWS = 100;
9+
const COLS = 20;
10+
const WARMUP = 5;
11+
const ITERATIONS = 50;
12+
13+
// Build a ROWS×COLS grid of (row, col, val) triples
14+
const rowArr: number[] = [];
15+
const colArr: number[] = [];
16+
const valArr: number[] = [];
17+
for (let r = 0; r < ROWS; r++) {
18+
for (let c = 0; c < COLS; c++) {
19+
rowArr.push(r);
20+
colArr.push(c);
21+
valArr.push(r * COLS + c + 0.5);
22+
}
23+
}
24+
const df = new DataFrame({ row: rowArr, col: colArr, val: valArr });
25+
26+
for (let i = 0; i < WARMUP; i++) {
27+
pivot(df, { index: "row", columns: "col", values: "val" });
28+
}
29+
30+
const start = performance.now();
31+
for (let i = 0; i < ITERATIONS; i++) {
32+
pivot(df, { index: "row", columns: "col", values: "val" });
33+
}
34+
const total = performance.now() - start;
35+
36+
console.log(
37+
JSON.stringify({
38+
function: "pivot_fn",
39+
mean_ms: Math.round((total / ITERATIONS) * 1000) / 1000,
40+
iterations: ITERATIONS,
41+
total_ms: Math.round(total * 1000) / 1000,
42+
}),
43+
);

0 commit comments

Comments
 (0)