Skip to content

Commit 0e5db21

Browse files
authored
Merge pull request #275 from githubnext/autoloop/perf-comparison
[Autoloop: perf-comparison]
2 parents e17a9c5 + e3a6fed commit 0e5db21

4 files changed

Lines changed: 235 additions & 0 deletions

File tree

benchmarks/pandas/bench_cum_ops.py

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
"""
2+
Benchmark: Series.cumsum / cumprod / cummax / cummin / DataFrame.cumsum
3+
Mirrors tsb bench_cum_ops.ts
4+
"""
5+
import json
6+
import time
7+
import pandas as pd
8+
9+
N = 100_000
10+
WARMUP = 5
11+
ITERS = 20
12+
13+
# Matching data
14+
data = [(i % 100) + 1 for i in range(N)]
15+
series = pd.Series(data, dtype=float)
16+
17+
col1 = [(i % 100) + 1 for i in range(N)]
18+
col2 = [((i * 3) % 100) + 1 for i in range(N)]
19+
df = pd.DataFrame({"a": col1, "b": col2}, dtype=float)
20+
21+
# Warm-up
22+
for _ in range(WARMUP):
23+
series.cumsum()
24+
series.cummax()
25+
df.cumsum()
26+
27+
# Measured: cumsum
28+
t0 = time.perf_counter()
29+
for _ in range(ITERS):
30+
series.cumsum()
31+
total_cumsum = (time.perf_counter() - t0) * 1000
32+
33+
# Measured: cumprod
34+
t0 = time.perf_counter()
35+
for _ in range(ITERS):
36+
series.cumprod()
37+
total_cumprod = (time.perf_counter() - t0) * 1000
38+
39+
# Measured: cummax
40+
t0 = time.perf_counter()
41+
for _ in range(ITERS):
42+
series.cummax()
43+
total_cummax = (time.perf_counter() - t0) * 1000
44+
45+
# Measured: cummin
46+
t0 = time.perf_counter()
47+
for _ in range(ITERS):
48+
series.cummin()
49+
total_cummin = (time.perf_counter() - t0) * 1000
50+
51+
# Measured: DataFrame.cumsum
52+
t0 = time.perf_counter()
53+
for _ in range(ITERS):
54+
df.cumsum()
55+
total_df = (time.perf_counter() - t0) * 1000
56+
57+
total_ms = total_cumsum + total_cumprod + total_cummax + total_cummin + total_df
58+
mean_ms = total_ms / (ITERS * 5)
59+
60+
print(json.dumps({
61+
"function": "cum_ops",
62+
"mean_ms": round(mean_ms, 4),
63+
"iterations": ITERS * 5,
64+
"total_ms": round(total_ms, 4),
65+
}))

benchmarks/pandas/bench_replace.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
"""
2+
Benchmark: Series.replace / DataFrame.replace
3+
Mirrors tsb bench_replace.ts
4+
"""
5+
import json
6+
import time
7+
import pandas as pd
8+
import numpy as np
9+
10+
N = 100_000
11+
WARMUP = 5
12+
ITERS = 20
13+
14+
# Build data matching the TypeScript benchmark
15+
data = [i % 10 for i in range(N)]
16+
series = pd.Series(data)
17+
18+
col1 = [i % 10 for i in range(N)]
19+
col2 = [(i * 3) % 10 for i in range(N)]
20+
df = pd.DataFrame({"a": col1, "b": col2})
21+
22+
# Warm-up
23+
for _ in range(WARMUP):
24+
series.replace(5, 99)
25+
df.replace(5, 99)
26+
27+
# Measured: Series.replace scalar
28+
t0 = time.perf_counter()
29+
for i in range(ITERS):
30+
series.replace(i % 10, 99)
31+
total_series = (time.perf_counter() - t0) * 1000
32+
33+
# Measured: DataFrame.replace scalar
34+
t0 = time.perf_counter()
35+
for i in range(ITERS):
36+
df.replace(i % 10, 99)
37+
total_df = (time.perf_counter() - t0) * 1000
38+
39+
total_ms = total_series + total_df
40+
mean_ms = total_ms / (ITERS * 2)
41+
42+
print(json.dumps({
43+
"function": "replace",
44+
"mean_ms": round(mean_ms, 4),
45+
"iterations": ITERS * 2,
46+
"total_ms": round(total_ms, 4),
47+
}))

benchmarks/tsb/bench_cum_ops.ts

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/**
2+
* Benchmark: cumsum / cumprod / cummax / cummin (Series and DataFrame)
3+
* Mirrors pandas Series.cumsum(), DataFrame.cumsum(), etc.
4+
*/
5+
import { Series, DataFrame } from "../../src/index.ts";
6+
import {
7+
cumsum,
8+
cumprod,
9+
cummax,
10+
cummin,
11+
dataFrameCumsum,
12+
} from "../../src/stats/cum_ops.ts";
13+
14+
const N = 100_000;
15+
16+
// Numeric series for cumsum/cumprod/cummax/cummin
17+
const data = Array.from({ length: N }, (_, i) => (i % 100) + 1);
18+
const series = new Series({ data });
19+
20+
// DataFrame with two columns
21+
const col1 = Array.from({ length: N }, (_, i) => (i % 100) + 1);
22+
const col2 = Array.from({ length: N }, (_, i) => ((i * 3) % 100) + 1);
23+
const df = DataFrame.fromColumns({ a: col1, b: col2 });
24+
25+
const WARMUP = 5;
26+
const ITERS = 20;
27+
28+
// --- warm-up ---
29+
for (let i = 0; i < WARMUP; i++) {
30+
cumsum(series);
31+
cummax(series);
32+
dataFrameCumsum(df);
33+
}
34+
35+
// --- measured: cumsum ---
36+
const t0cs = performance.now();
37+
for (let i = 0; i < ITERS; i++) cumsum(series);
38+
const totalCumsum = performance.now() - t0cs;
39+
40+
// --- measured: cumprod ---
41+
const t0cp = performance.now();
42+
for (let i = 0; i < ITERS; i++) cumprod(series);
43+
const totalCumprod = performance.now() - t0cp;
44+
45+
// --- measured: cummax ---
46+
const t0cx = performance.now();
47+
for (let i = 0; i < ITERS; i++) cummax(series);
48+
const totalCummax = performance.now() - t0cx;
49+
50+
// --- measured: cummin ---
51+
const t0cn = performance.now();
52+
for (let i = 0; i < ITERS; i++) cummin(series);
53+
const totalCummin = performance.now() - t0cn;
54+
55+
// --- measured: dataFrameCumsum ---
56+
const t0df = performance.now();
57+
for (let i = 0; i < ITERS; i++) dataFrameCumsum(df);
58+
const totalDf = performance.now() - t0df;
59+
60+
const total_ms = totalCumsum + totalCumprod + totalCummax + totalCummin + totalDf;
61+
const mean_ms = total_ms / (ITERS * 5);
62+
63+
console.log(
64+
JSON.stringify({
65+
function: "cum_ops",
66+
mean_ms: parseFloat(mean_ms.toFixed(4)),
67+
iterations: ITERS * 5,
68+
total_ms: parseFloat(total_ms.toFixed(4)),
69+
}),
70+
);

benchmarks/tsb/bench_replace.ts

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/**
2+
* Benchmark: replaceSeries / replaceDataFrame
3+
* Mirrors pandas Series.replace() and DataFrame.replace().
4+
*/
5+
import { Series, DataFrame } from "../../src/index.ts";
6+
import { replaceSeries, replaceDataFrame } from "../../src/stats/replace.ts";
7+
8+
const N = 100_000;
9+
10+
// Build a numeric series with values 0–9 (cycled) for scalar replace
11+
const data = Array.from({ length: N }, (_, i) => i % 10);
12+
const series = new Series({ data });
13+
14+
// Build a DataFrame with two numeric columns
15+
const col1 = Array.from({ length: N }, (_, i) => i % 10);
16+
const col2 = Array.from({ length: N }, (_, i) => (i * 3) % 10);
17+
const df = DataFrame.fromColumns({ a: col1, b: col2 });
18+
19+
const WARMUP = 5;
20+
const ITERS = 20;
21+
22+
// --- warm-up ---
23+
for (let i = 0; i < WARMUP; i++) {
24+
replaceSeries(series, { toReplace: 5, value: 99 });
25+
replaceDataFrame(df, { toReplace: 5, value: 99 });
26+
}
27+
28+
// --- measured: replaceSeries scalar ---
29+
const t0s = performance.now();
30+
for (let i = 0; i < ITERS; i++) {
31+
replaceSeries(series, { toReplace: i % 10, value: 99 });
32+
}
33+
const totalSeries = performance.now() - t0s;
34+
35+
// --- measured: replaceDataFrame scalar ---
36+
const t0d = performance.now();
37+
for (let i = 0; i < ITERS; i++) {
38+
replaceDataFrame(df, { toReplace: i % 10, value: 99 });
39+
}
40+
const totalDf = performance.now() - t0d;
41+
42+
// Report the average of the two operations
43+
const total_ms = totalSeries + totalDf;
44+
const mean_ms = total_ms / (ITERS * 2);
45+
46+
console.log(
47+
JSON.stringify({
48+
function: "replace",
49+
mean_ms: parseFloat(mean_ms.toFixed(4)),
50+
iterations: ITERS * 2,
51+
total_ms: parseFloat(total_ms.toFixed(4)),
52+
}),
53+
);

0 commit comments

Comments
 (0)