Skip to content

Commit 653b095

Browse files
Iteration 259: 7 new benchmark pairs (606 total, +2 vs best 604)
Added benchmark pairs for: - dataframe_ffill_bfill_fn (dataFrameFfill/dataFrameBfill standalone) - series_ffill_bfill_fn (ffillSeries/bfillSeries standalone) - dataframe_diff_shift_fn (diffDataFrame/shiftDataFrame standalone) - interval_range_fn (intervalRange standalone) - date_range_fn (dateRange standalone function) - format_timedelta_fn (formatTimedelta/parseFrac) - advance_date_fn (advanceDate/parseFreq) Run: https://github.com/githubnext/tsessebe/actions/runs/24677958917 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent fc3d0cf commit 653b095

14 files changed

Lines changed: 541 additions & 0 deletions
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
"""
2+
Benchmark: pandas DateOffset arithmetic — advance a date by a frequency.
3+
Mirrors tsb bench_advance_date_fn.ts (advanceDate/parseFreq).
4+
Outputs JSON: {"function": "advance_date_fn", "mean_ms": ..., "iterations": ..., "total_ms": ...}
5+
"""
6+
import json
7+
import time
8+
import pandas as pd
9+
from pandas.tseries.offsets import Day, BusinessDay, Hour, MonthBegin, MonthEnd, Week
10+
11+
WARMUP = 5
12+
ITERATIONS = 50
13+
14+
d = pd.Timestamp("2020-01-15")
15+
offsets = [Day(1), Day(2), Hour(1), Hour(3), MonthBegin(1), MonthEnd(1), Week(1), BusinessDay(1)]
16+
17+
for _ in range(WARMUP):
18+
for off in offsets:
19+
d + off
20+
21+
times = []
22+
for _ in range(ITERATIONS):
23+
t0 = time.perf_counter()
24+
for _ in range(1000):
25+
for off in offsets:
26+
d + off
27+
times.append((time.perf_counter() - t0) * 1000)
28+
29+
total_ms = sum(times)
30+
print(json.dumps({
31+
"function": "advance_date_fn",
32+
"mean_ms": round(total_ms / ITERATIONS, 3),
33+
"iterations": ITERATIONS,
34+
"total_ms": round(total_ms, 3),
35+
}))
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
"""
2+
Benchmark: pandas DataFrame.diff() / DataFrame.shift() — standalone diff and shift.
3+
Mirrors tsb bench_dataframe_diff_shift_fn.ts (standalone diffDataFrame/shiftDataFrame).
4+
Outputs JSON: {"function": "dataframe_diff_shift_fn", "mean_ms": ..., "iterations": ..., "total_ms": ...}
5+
"""
6+
import json
7+
import time
8+
import numpy as np
9+
import pandas as pd
10+
11+
SIZE = 100_000
12+
WARMUP = 5
13+
ITERATIONS = 30
14+
15+
df = pd.DataFrame({
16+
"a": np.arange(SIZE, dtype=float),
17+
"b": np.arange(SIZE, dtype=float) * 0.5 + 100,
18+
"c": np.sin(np.arange(SIZE) * 0.01) * 1000,
19+
})
20+
21+
for _ in range(WARMUP):
22+
df.diff(periods=1)
23+
df.shift(periods=3)
24+
25+
times = []
26+
for _ in range(ITERATIONS):
27+
t0 = time.perf_counter()
28+
df.diff(periods=1)
29+
df.shift(periods=3)
30+
times.append((time.perf_counter() - t0) * 1000)
31+
32+
total_ms = sum(times)
33+
print(json.dumps({
34+
"function": "dataframe_diff_shift_fn",
35+
"mean_ms": round(total_ms / ITERATIONS, 3),
36+
"iterations": ITERATIONS,
37+
"total_ms": round(total_ms, 3),
38+
}))
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
"""
2+
Benchmark: pandas DataFrame.ffill() / DataFrame.bfill() — forward/backward fill.
3+
Mirrors tsb bench_dataframe_ffill_bfill_fn.ts (standalone dataFrameFfill/dataFrameBfill).
4+
Outputs JSON: {"function": "dataframe_ffill_bfill_fn", "mean_ms": ..., "iterations": ..., "total_ms": ...}
5+
"""
6+
import json
7+
import time
8+
import numpy as np
9+
import pandas as pd
10+
11+
SIZE = 100_000
12+
WARMUP = 5
13+
ITERATIONS = 30
14+
15+
rng = np.random.default_rng(42)
16+
a = np.where(np.arange(SIZE) % 5 == 0, np.nan, np.arange(SIZE, dtype=float))
17+
b = np.where(np.arange(SIZE) % 7 == 0, np.nan, np.arange(SIZE, dtype=float) * 0.5)
18+
c = np.where(np.arange(SIZE) % 3 == 0, np.nan, np.arange(SIZE, dtype=float) * 2.0)
19+
20+
df = pd.DataFrame({"a": a, "b": b, "c": c})
21+
22+
for _ in range(WARMUP):
23+
df.ffill()
24+
df.bfill()
25+
26+
times = []
27+
for _ in range(ITERATIONS):
28+
t0 = time.perf_counter()
29+
df.ffill()
30+
df.bfill()
31+
times.append((time.perf_counter() - t0) * 1000)
32+
33+
total_ms = sum(times)
34+
print(json.dumps({
35+
"function": "dataframe_ffill_bfill_fn",
36+
"mean_ms": round(total_ms / ITERATIONS, 3),
37+
"iterations": ITERATIONS,
38+
"total_ms": round(total_ms, 3),
39+
}))
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
"""
2+
Benchmark: pandas pd.date_range() — generate date sequences.
3+
Mirrors tsb bench_date_range_fn.ts (dateRange standalone function).
4+
Outputs JSON: {"function": "date_range_fn", "mean_ms": ..., "iterations": ..., "total_ms": ...}
5+
"""
6+
import json
7+
import time
8+
import pandas as pd
9+
10+
WARMUP = 5
11+
ITERATIONS = 50
12+
13+
start = "2020-01-01"
14+
end = "2020-12-31"
15+
16+
for _ in range(WARMUP):
17+
pd.date_range(start=start, end=end, freq="D")
18+
pd.date_range(start=start, periods=1000, freq="h")
19+
20+
times = []
21+
for _ in range(ITERATIONS):
22+
t0 = time.perf_counter()
23+
pd.date_range(start=start, end=end, freq="D")
24+
pd.date_range(start=start, periods=1000, freq="h")
25+
times.append((time.perf_counter() - t0) * 1000)
26+
27+
total_ms = sum(times)
28+
print(json.dumps({
29+
"function": "date_range_fn",
30+
"mean_ms": round(total_ms / ITERATIONS, 3),
31+
"iterations": ITERATIONS,
32+
"total_ms": round(total_ms, 3),
33+
}))
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
"""
2+
Benchmark: pandas Timedelta string formatting — str(Timedelta) and parsing.
3+
Mirrors tsb bench_format_timedelta_fn.ts (formatTimedelta/parseFrac).
4+
Outputs JSON: {"function": "format_timedelta_fn", "mean_ms": ..., "iterations": ..., "total_ms": ...}
5+
"""
6+
import json
7+
import time
8+
import pandas as pd
9+
10+
WARMUP = 5
11+
ITERATIONS = 50
12+
13+
tds = [
14+
pd.Timedelta(days=1),
15+
pd.Timedelta(seconds=3661),
16+
pd.Timedelta(milliseconds=90061001),
17+
pd.Timedelta(seconds=0),
18+
pd.Timedelta(seconds=-86400),
19+
]
20+
21+
for _ in range(WARMUP):
22+
for td in tds:
23+
str(td)
24+
25+
times = []
26+
for _ in range(ITERATIONS):
27+
t0 = time.perf_counter()
28+
for _ in range(1000):
29+
for td in tds:
30+
str(td)
31+
times.append((time.perf_counter() - t0) * 1000)
32+
33+
total_ms = sum(times)
34+
print(json.dumps({
35+
"function": "format_timedelta_fn",
36+
"mean_ms": round(total_ms / ITERATIONS, 3),
37+
"iterations": ITERATIONS,
38+
"total_ms": round(total_ms, 3),
39+
}))
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
"""
2+
Benchmark: pandas pd.interval_range() — create an IntervalIndex from start/end with periods.
3+
Mirrors tsb bench_interval_range_fn.ts (intervalRange standalone function).
4+
Outputs JSON: {"function": "interval_range_fn", "mean_ms": ..., "iterations": ..., "total_ms": ...}
5+
"""
6+
import json
7+
import time
8+
import pandas as pd
9+
10+
WARMUP = 5
11+
ITERATIONS = 50
12+
13+
for _ in range(WARMUP):
14+
pd.interval_range(start=0, end=1000, periods=10_000)
15+
pd.interval_range(start=0, end=100, freq=0.01)
16+
17+
times = []
18+
for _ in range(ITERATIONS):
19+
t0 = time.perf_counter()
20+
pd.interval_range(start=0, end=1000, periods=10_000)
21+
pd.interval_range(start=0, end=100, freq=0.01)
22+
times.append((time.perf_counter() - t0) * 1000)
23+
24+
total_ms = sum(times)
25+
print(json.dumps({
26+
"function": "interval_range_fn",
27+
"mean_ms": round(total_ms / ITERATIONS, 3),
28+
"iterations": ITERATIONS,
29+
"total_ms": round(total_ms, 3),
30+
}))
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
"""
2+
Benchmark: pandas Series.ffill() / Series.bfill() — forward/backward fill for Series.
3+
Mirrors tsb bench_series_ffill_bfill_fn.ts (standalone ffillSeries/bfillSeries).
4+
Outputs JSON: {"function": "series_ffill_bfill_fn", "mean_ms": ..., "iterations": ..., "total_ms": ...}
5+
"""
6+
import json
7+
import time
8+
import numpy as np
9+
import pandas as pd
10+
11+
SIZE = 100_000
12+
WARMUP = 5
13+
ITERATIONS = 50
14+
15+
data = [float("nan") if i % 5 == 0 else i * 1.0 for i in range(SIZE)]
16+
s = pd.Series(data)
17+
18+
for _ in range(WARMUP):
19+
s.ffill()
20+
s.bfill()
21+
22+
times = []
23+
for _ in range(ITERATIONS):
24+
t0 = time.perf_counter()
25+
s.ffill()
26+
s.bfill()
27+
times.append((time.perf_counter() - t0) * 1000)
28+
29+
total_ms = sum(times)
30+
print(json.dumps({
31+
"function": "series_ffill_bfill_fn",
32+
"mean_ms": round(total_ms / ITERATIONS, 3),
33+
"iterations": ITERATIONS,
34+
"total_ms": round(total_ms, 3),
35+
}))
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/**
2+
* Benchmark: advanceDate / parseFreq — advance a Date by a parsed frequency and parse freq strings.
3+
* Mirrors pandas DateOffset arithmetic and freq parsing.
4+
* Outputs JSON: {"function": "advance_date_fn", "mean_ms": ..., "iterations": ..., "total_ms": ...}
5+
*/
6+
import { advanceDate, parseFreq } from "../../src/index.ts";
7+
8+
const WARMUP = 5;
9+
const ITERATIONS = 50;
10+
11+
const d = new Date("2020-01-15");
12+
const freqs = ["D", "2D", "h", "3h", "MS", "ME", "W", "B"];
13+
const parsedFreqs = freqs.map((f) => parseFreq(f));
14+
15+
for (let i = 0; i < WARMUP; i++) {
16+
for (const pf of parsedFreqs) advanceDate(d, pf);
17+
for (const f of freqs) parseFreq(f);
18+
}
19+
20+
const times: number[] = [];
21+
for (let i = 0; i < ITERATIONS; i++) {
22+
const t0 = performance.now();
23+
for (let j = 0; j < 1000; j++) {
24+
for (const pf of parsedFreqs) advanceDate(d, pf);
25+
for (const f of freqs) parseFreq(f);
26+
}
27+
times.push(performance.now() - t0);
28+
}
29+
30+
const total = times.reduce((a, b) => a + b, 0);
31+
console.log(
32+
JSON.stringify({
33+
function: "advance_date_fn",
34+
mean_ms: round3(total / ITERATIONS),
35+
iterations: ITERATIONS,
36+
total_ms: round3(total),
37+
}),
38+
);
39+
40+
function round3(v: number): number {
41+
return Math.round(v * 1000) / 1000;
42+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/**
2+
* Benchmark: diffDataFrame / shiftDataFrame — standalone diff and shift for DataFrames.
3+
* Mirrors pandas DataFrame.diff() / DataFrame.shift().
4+
* Outputs JSON: {"function": "dataframe_diff_shift_fn", "mean_ms": ..., "iterations": ..., "total_ms": ...}
5+
*/
6+
import { DataFrame, diffDataFrame, shiftDataFrame } from "../../src/index.ts";
7+
8+
const SIZE = 100_000;
9+
const WARMUP = 5;
10+
const ITERATIONS = 30;
11+
12+
const df = DataFrame.fromColumns({
13+
a: Array.from({ length: SIZE }, (_, i) => i * 1.0),
14+
b: Array.from({ length: SIZE }, (_, i) => i * 0.5 + 100),
15+
c: Array.from({ length: SIZE }, (_, i) => Math.sin(i * 0.01) * 1000),
16+
});
17+
18+
for (let i = 0; i < WARMUP; i++) {
19+
diffDataFrame(df, { periods: 1 });
20+
shiftDataFrame(df, { periods: 3 });
21+
}
22+
23+
const times: number[] = [];
24+
for (let i = 0; i < ITERATIONS; i++) {
25+
const t0 = performance.now();
26+
diffDataFrame(df, { periods: 1 });
27+
shiftDataFrame(df, { periods: 3 });
28+
times.push(performance.now() - t0);
29+
}
30+
31+
const total = times.reduce((a, b) => a + b, 0);
32+
console.log(
33+
JSON.stringify({
34+
function: "dataframe_diff_shift_fn",
35+
mean_ms: round3(total / ITERATIONS),
36+
iterations: ITERATIONS,
37+
total_ms: round3(total),
38+
}),
39+
);
40+
41+
function round3(v: number): number {
42+
return Math.round(v * 1000) / 1000;
43+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/**
2+
* Benchmark: dataFrameFfill / dataFrameBfill — standalone forward/backward fill for DataFrames.
3+
* Mirrors pandas DataFrame.ffill() / DataFrame.bfill().
4+
* Outputs JSON: {"function": "dataframe_ffill_bfill_fn", "mean_ms": ..., "iterations": ..., "total_ms": ...}
5+
*/
6+
import { DataFrame, dataFrameFfill, dataFrameBfill } from "../../src/index.ts";
7+
8+
const SIZE = 100_000;
9+
const WARMUP = 5;
10+
const ITERATIONS = 30;
11+
12+
const df = DataFrame.fromColumns({
13+
a: Array.from({ length: SIZE }, (_, i) => (i % 5 === 0 ? null : i * 1.0)),
14+
b: Array.from({ length: SIZE }, (_, i) => (i % 7 === 0 ? null : i * 0.5)),
15+
c: Array.from({ length: SIZE }, (_, i) => (i % 3 === 0 ? null : i * 2.0)),
16+
});
17+
18+
for (let i = 0; i < WARMUP; i++) {
19+
dataFrameFfill(df);
20+
dataFrameBfill(df);
21+
}
22+
23+
const times: number[] = [];
24+
for (let i = 0; i < ITERATIONS; i++) {
25+
const t0 = performance.now();
26+
dataFrameFfill(df);
27+
dataFrameBfill(df);
28+
times.push(performance.now() - t0);
29+
}
30+
31+
const total = times.reduce((a, b) => a + b, 0);
32+
console.log(
33+
JSON.stringify({
34+
function: "dataframe_ffill_bfill_fn",
35+
mean_ms: round3(total / ITERATIONS),
36+
iterations: ITERATIONS,
37+
total_ms: round3(total),
38+
}),
39+
);
40+
41+
function round3(v: number): number {
42+
return Math.round(v * 1000) / 1000;
43+
}

0 commit comments

Comments
 (0)