Skip to content

Commit b5584cf

Browse files
[Autoloop: perf-comparison] Iteration 378: add 3 benchmark pairs (merge_ordered_ffill, merge_ordered_by, grouper_class)
Run: https://github.com/githubnext/tsb/actions/runs/28315875254 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 9198f7a commit b5584cf

6 files changed

Lines changed: 258 additions & 0 deletions
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
"""Benchmark: pd.Grouper construction and isinstance checks — 50k iterations."""
2+
import json
3+
import time
4+
5+
import pandas as pd
6+
7+
WARMUP = 5
8+
ITERATIONS = 50_000
9+
10+
11+
def run_groupers() -> None:
12+
g1 = pd.Grouper(key="col_a")
13+
g2 = pd.Grouper(key="date", sort=True)
14+
g3 = pd.Grouper(key="category", dropna=False)
15+
16+
isinstance(g1, pd.Grouper)
17+
isinstance(g2, pd.Grouper)
18+
isinstance(g3, pd.Grouper)
19+
isinstance("not_a_grouper", pd.Grouper)
20+
isinstance(42, pd.Grouper)
21+
22+
str(g1)
23+
str(g2)
24+
str(g3)
25+
26+
27+
for _ in range(WARMUP):
28+
run_groupers()
29+
30+
start = time.perf_counter()
31+
for _ in range(ITERATIONS):
32+
run_groupers()
33+
total = (time.perf_counter() - start) * 1000
34+
35+
print(
36+
json.dumps(
37+
{
38+
"function": "grouper_class",
39+
"mean_ms": total / ITERATIONS,
40+
"iterations": ITERATIONS,
41+
"total_ms": total,
42+
}
43+
)
44+
)
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
"""Benchmark: pd.merge_ordered with left_by grouping — two 3k-row DataFrames, 10 groups."""
2+
import json
3+
import time
4+
5+
import pandas as pd
6+
7+
N = 3_000
8+
GROUPS = 10
9+
PER_GROUP = N // GROUPS
10+
WARMUP = 2
11+
ITERATIONS = 8
12+
13+
grp_left = [f"g{g}" for g in range(GROUPS) for _ in range(PER_GROUP)]
14+
t_left = [j * 2 for _ in range(GROUPS) for j in range(PER_GROUP)]
15+
v1 = [g * PER_GROUP + j for g in range(GROUPS) for j in range(PER_GROUP)]
16+
17+
grp_right = [f"g{g}" for g in range(GROUPS) for _ in range(PER_GROUP)]
18+
t_right = [j * 3 for _ in range(GROUPS) for j in range(PER_GROUP)]
19+
v2 = [g * PER_GROUP + j for g in range(GROUPS) for j in range(PER_GROUP)]
20+
21+
df1 = pd.DataFrame({"grp": grp_left, "t": t_left, "val1": v1})
22+
df2 = pd.DataFrame({"grp": grp_right, "t": t_right, "val2": v2})
23+
24+
for _ in range(WARMUP):
25+
pd.merge_ordered(df1, df2, on="t", left_by="grp", right_by="grp")
26+
27+
start = time.perf_counter()
28+
for _ in range(ITERATIONS):
29+
pd.merge_ordered(df1, df2, on="t", left_by="grp", right_by="grp")
30+
total = (time.perf_counter() - start) * 1000
31+
32+
print(
33+
json.dumps(
34+
{
35+
"function": "merge_ordered_by",
36+
"mean_ms": total / ITERATIONS,
37+
"iterations": ITERATIONS,
38+
"total_ms": total,
39+
}
40+
)
41+
)
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
"""Benchmark: pd.merge_ordered with fill_method='ffill' — two 5k-row DataFrames."""
2+
import json
3+
import time
4+
5+
import pandas as pd
6+
7+
N = 5_000
8+
WARMUP = 2
9+
ITERATIONS = 8
10+
11+
keys1 = list(range(0, N * 2, 2))
12+
vals1 = [i * 1.0 for i in range(N)]
13+
keys2 = list(range(0, N * 3, 3))
14+
vals2 = [i * 2.0 for i in range(N)]
15+
16+
df1 = pd.DataFrame({"key": keys1, "val1": vals1})
17+
df2 = pd.DataFrame({"key": keys2, "val2": vals2})
18+
19+
for _ in range(WARMUP):
20+
pd.merge_ordered(df1, df2, on="key", fill_method="ffill")
21+
22+
start = time.perf_counter()
23+
for _ in range(ITERATIONS):
24+
pd.merge_ordered(df1, df2, on="key", fill_method="ffill")
25+
total = (time.perf_counter() - start) * 1000
26+
27+
print(
28+
json.dumps(
29+
{
30+
"function": "merge_ordered_ffill",
31+
"mean_ms": total / ITERATIONS,
32+
"iterations": ITERATIONS,
33+
"total_ms": total,
34+
}
35+
)
36+
)
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/**
2+
* Benchmark: Grouper class — construction, predicates, and isGrouper on 50k iterations.
3+
* Outputs JSON: {"function": "grouper_class", "mean_ms": ..., "iterations": ..., "total_ms": ...}
4+
*/
5+
import { Grouper, isGrouper } from "../../src/index.ts";
6+
7+
const WARMUP = 5;
8+
const ITERATIONS = 50_000;
9+
10+
function runGroupers(): void {
11+
const g1 = new Grouper({ key: "col_a" });
12+
const g2 = new Grouper({ key: "date", sort: true });
13+
const g3 = new Grouper({ key: "category", dropna: false });
14+
15+
isGrouper(g1);
16+
isGrouper(g2);
17+
isGrouper(g3);
18+
isGrouper("not_a_grouper");
19+
isGrouper(42);
20+
21+
g1.isKeyGrouper();
22+
g2.isKeyGrouper();
23+
g3.isKeyGrouper();
24+
g1.isLevelGrouper();
25+
26+
g1.toString();
27+
g2.toString();
28+
g3.toString();
29+
}
30+
31+
for (let i = 0; i < WARMUP; i++) runGroupers();
32+
33+
const start = performance.now();
34+
for (let i = 0; i < ITERATIONS; i++) runGroupers();
35+
const total = performance.now() - start;
36+
37+
console.log(
38+
JSON.stringify({
39+
function: "grouper_class",
40+
mean_ms: total / ITERATIONS,
41+
iterations: ITERATIONS,
42+
total_ms: total,
43+
}),
44+
);
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/**
2+
* Benchmark: mergeOrdered with left_by grouping — two 3k-row DataFrames, 10 groups.
3+
* Outputs JSON: {"function": "merge_ordered_by", "mean_ms": ..., "iterations": ..., "total_ms": ...}
4+
*/
5+
import { DataFrame, mergeOrdered } from "../../src/index.ts";
6+
7+
const N = 3_000;
8+
const GROUPS = 10;
9+
const PER_GROUP = N / GROUPS;
10+
const WARMUP = 2;
11+
const ITERATIONS = 8;
12+
13+
// Build sorted data by (grp, t)
14+
const grpLeft: string[] = [];
15+
const tLeft: number[] = [];
16+
const v1: number[] = [];
17+
for (let g = 0; g < GROUPS; g++) {
18+
for (let j = 0; j < PER_GROUP; j++) {
19+
grpLeft.push(`g${g}`);
20+
tLeft.push(j * 2);
21+
v1.push(g * PER_GROUP + j);
22+
}
23+
}
24+
25+
const grpRight: string[] = [];
26+
const tRight: number[] = [];
27+
const v2: number[] = [];
28+
for (let g = 0; g < GROUPS; g++) {
29+
for (let j = 0; j < PER_GROUP; j++) {
30+
grpRight.push(`g${g}`);
31+
tRight.push(j * 3);
32+
v2.push(g * PER_GROUP + j);
33+
}
34+
}
35+
36+
const df1 = DataFrame.fromColumns({ grp: grpLeft, t: tLeft, val1: v1 });
37+
const df2 = DataFrame.fromColumns({ grp: grpRight, t: tRight, val2: v2 });
38+
39+
for (let i = 0; i < WARMUP; i++) {
40+
mergeOrdered(df1, df2, { on: "t", left_by: "grp", right_by: "grp" });
41+
}
42+
43+
const start = performance.now();
44+
for (let i = 0; i < ITERATIONS; i++) {
45+
mergeOrdered(df1, df2, { on: "t", left_by: "grp", right_by: "grp" });
46+
}
47+
const total = performance.now() - start;
48+
49+
console.log(
50+
JSON.stringify({
51+
function: "merge_ordered_by",
52+
mean_ms: total / ITERATIONS,
53+
iterations: ITERATIONS,
54+
total_ms: total,
55+
}),
56+
);
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/**
2+
* Benchmark: mergeOrdered with fill_method "ffill" — two 5k-row DataFrames with interleaved keys.
3+
* Outputs JSON: {"function": "merge_ordered_ffill", "mean_ms": ..., "iterations": ..., "total_ms": ...}
4+
*/
5+
import { DataFrame, mergeOrdered } from "../../src/index.ts";
6+
7+
const N = 5_000;
8+
const WARMUP = 2;
9+
const ITERATIONS = 8;
10+
11+
// Even-numbered keys on left, multiples-of-3 on right → many gaps filled by ffill
12+
const keys1 = Array.from({ length: N }, (_, i) => i * 2);
13+
const vals1 = Array.from({ length: N }, (_, i) => i * 1.0);
14+
const keys2 = Array.from({ length: N }, (_, i) => i * 3);
15+
const vals2 = Array.from({ length: N }, (_, i) => i * 2.0);
16+
17+
const df1 = DataFrame.fromColumns({ key: keys1, val1: vals1 });
18+
const df2 = DataFrame.fromColumns({ key: keys2, val2: vals2 });
19+
20+
for (let i = 0; i < WARMUP; i++) {
21+
mergeOrdered(df1, df2, { on: "key", fill_method: "ffill" });
22+
}
23+
24+
const start = performance.now();
25+
for (let i = 0; i < ITERATIONS; i++) {
26+
mergeOrdered(df1, df2, { on: "key", fill_method: "ffill" });
27+
}
28+
const total = performance.now() - start;
29+
30+
console.log(
31+
JSON.stringify({
32+
function: "merge_ordered_ffill",
33+
mean_ms: total / ITERATIONS,
34+
iterations: ITERATIONS,
35+
total_ms: total,
36+
}),
37+
);

0 commit comments

Comments
 (0)