Skip to content

Commit 28a1a07

Browse files
Iteration 132: Add 8 benchmark pairs (380 total, +8 vs best 372)
Added: searchsorted, astype_series, timestamp, date_offset, timedelta, json_normalize, period, interval. Run: https://github.com/githubnext/tsessebe/actions/runs/24531850677 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent a92abcc commit 28a1a07

16 files changed

Lines changed: 573 additions & 0 deletions
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
"""Benchmark: Series.astype() — cast Series dtype."""
2+
import json, time
3+
import pandas as pd
4+
5+
SIZE = 100_000
6+
WARMUP = 5
7+
ITERATIONS = 50
8+
9+
float_series = pd.Series([i * 1.5 for i in range(SIZE)])
10+
int_series = pd.Series([i for i in range(SIZE)])
11+
12+
for _ in range(WARMUP):
13+
float_series.astype("int32")
14+
int_series.astype("float64")
15+
int_series.astype("str")
16+
17+
times = []
18+
for _ in range(ITERATIONS):
19+
t0 = time.perf_counter()
20+
float_series.astype("int32")
21+
int_series.astype("float64")
22+
int_series.astype("str")
23+
times.append((time.perf_counter() - t0) * 1000)
24+
25+
total_ms = sum(times)
26+
print(json.dumps({"function":"astype_series","mean_ms":round(total_ms/ITERATIONS,3),"iterations":ITERATIONS,"total_ms":round(total_ms,3)}))
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
"""Benchmark: DateOffset — MonthEnd, BusinessDay, YearBegin apply."""
2+
import json, time
3+
import pandas as pd
4+
from pandas.tseries.offsets import MonthEnd, BusinessDay, YearBegin, Day
5+
from datetime import datetime, timezone, timedelta
6+
7+
SIZE = 10_000
8+
WARMUP = 5
9+
ITERATIONS = 50
10+
11+
month_end = MonthEnd(1)
12+
biz_day = BusinessDay(5)
13+
year_begin = YearBegin(1)
14+
day_off = Day(30)
15+
base = pd.Timestamp("2020-01-15", tz="UTC")
16+
dates = [base + timedelta(days=i) for i in range(SIZE)]
17+
18+
for _ in range(WARMUP):
19+
for d in dates:
20+
d + month_end
21+
d + biz_day
22+
d + year_begin
23+
d + day_off
24+
25+
times = []
26+
for _ in range(ITERATIONS):
27+
t0 = time.perf_counter()
28+
for d in dates:
29+
d + month_end
30+
d + biz_day
31+
d + year_begin
32+
d + day_off
33+
times.append((time.perf_counter() - t0) * 1000)
34+
35+
total_ms = sum(times)
36+
print(json.dumps({"function":"date_offset","mean_ms":round(total_ms/ITERATIONS,3),"iterations":ITERATIONS,"total_ms":round(total_ms,3)}))
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
"""Benchmark: Interval / IntervalIndex — closed/open intervals."""
2+
import json, time
3+
import pandas as pd
4+
5+
SIZE = 10_000
6+
WARMUP = 5
7+
ITERATIONS = 50
8+
9+
intervals = [pd.Interval(i, i + 1) for i in range(SIZE)]
10+
breaks = list(range(1_001))
11+
12+
for _ in range(WARMUP):
13+
for iv in intervals[:100]:
14+
iv.mid in iv
15+
_ = iv.length
16+
str(iv)
17+
pd.IntervalIndex.from_breaks(breaks)
18+
19+
times = []
20+
for _ in range(ITERATIONS):
21+
t0 = time.perf_counter()
22+
for iv in intervals:
23+
iv.mid in iv
24+
_ = iv.length
25+
str(iv)
26+
pd.IntervalIndex.from_breaks(breaks)
27+
times.append((time.perf_counter() - t0) * 1000)
28+
29+
total_ms = sum(times)
30+
print(json.dumps({"function":"interval","mean_ms":round(total_ms/ITERATIONS,3),"iterations":ITERATIONS,"total_ms":round(total_ms,3)}))
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
"""Benchmark: json_normalize — flatten nested JSON to a flat DataFrame."""
2+
import json, time
3+
import pandas as pd
4+
5+
SIZE = 1_000
6+
WARMUP = 5
7+
ITERATIONS = 50
8+
9+
records = [
10+
{"id": i, "name": f"user_{i}", "address": {"city": f"city_{i % 10}", "zip": str(10000 + i)}, "scores": [i, i+1, i+2]}
11+
for i in range(SIZE)
12+
]
13+
14+
for _ in range(WARMUP):
15+
pd.json_normalize(records, max_level=2)
16+
17+
times = []
18+
for _ in range(ITERATIONS):
19+
t0 = time.perf_counter()
20+
pd.json_normalize(records, max_level=2)
21+
times.append((time.perf_counter() - t0) * 1000)
22+
23+
total_ms = sum(times)
24+
print(json.dumps({"function":"json_normalize","mean_ms":round(total_ms/ITERATIONS,3),"iterations":ITERATIONS,"total_ms":round(total_ms,3)}))

benchmarks/pandas/bench_period.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
"""Benchmark: Period / PeriodIndex — fixed-frequency time spans."""
2+
import json, time
3+
import pandas as pd
4+
5+
SIZE = 10_000
6+
WARMUP = 5
7+
ITERATIONS = 50
8+
9+
base = pd.Period("2020-01-01", freq="D")
10+
periods = [base + i for i in range(SIZE)]
11+
12+
start_q = pd.Period("2000Q1", freq="Q")
13+
end_q = pd.Period("2024Q4", freq="Q")
14+
15+
for _ in range(WARMUP):
16+
for p in periods[:100]:
17+
str(p)
18+
p + 1
19+
pd.period_range(start=start_q, end=end_q, freq="Q")
20+
21+
times = []
22+
for _ in range(ITERATIONS):
23+
t0 = time.perf_counter()
24+
for p in periods:
25+
str(p)
26+
p + 1
27+
pd.period_range(start=start_q, end=end_q, freq="Q")
28+
times.append((time.perf_counter() - t0) * 1000)
29+
30+
total_ms = sum(times)
31+
print(json.dumps({"function":"period","mean_ms":round(total_ms/ITERATIONS,3),"iterations":ITERATIONS,"total_ms":round(total_ms,3)}))
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
"""Benchmark: searchsorted / searchsortedMany — binary search on sorted arrays."""
2+
import json, time
3+
import numpy as np
4+
5+
SIZE = 100_000
6+
WARMUP = 5
7+
ITERATIONS = 50
8+
9+
sorted_arr = np.array([i * 2 for i in range(SIZE)])
10+
needles = np.array([i * 200 for i in range(1_000)])
11+
12+
for _ in range(WARMUP):
13+
np.searchsorted(sorted_arr, 50_000)
14+
np.searchsorted(sorted_arr, needles)
15+
16+
times = []
17+
for _ in range(ITERATIONS):
18+
t0 = time.perf_counter()
19+
np.searchsorted(sorted_arr, 50_000)
20+
np.searchsorted(sorted_arr, needles)
21+
times.append((time.perf_counter() - t0) * 1000)
22+
23+
total_ms = sum(times)
24+
print(json.dumps({"function":"searchsorted","mean_ms":round(total_ms/ITERATIONS,3),"iterations":ITERATIONS,"total_ms":round(total_ms,3)}))
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
"""Benchmark: Timedelta — construction and arithmetic."""
2+
import json, time
3+
import pandas as pd
4+
5+
SIZE = 10_000
6+
WARMUP = 5
7+
ITERATIONS = 50
8+
9+
td1 = pd.Timedelta(days=1, hours=2, minutes=30)
10+
td2 = pd.Timedelta(hours=3, minutes=45, seconds=10)
11+
deltas = [pd.Timedelta(days=i % 365, hours=i % 24) for i in range(SIZE)]
12+
13+
for _ in range(WARMUP):
14+
for d in deltas:
15+
d + td1
16+
d - td2
17+
_ = d.total_seconds() / 3600
18+
_ = d.total_seconds()
19+
20+
times = []
21+
for _ in range(ITERATIONS):
22+
t0 = time.perf_counter()
23+
for d in deltas:
24+
d + td1
25+
d - td2
26+
_ = d.total_seconds() / 3600
27+
_ = d.total_seconds()
28+
times.append((time.perf_counter() - t0) * 1000)
29+
30+
total_ms = sum(times)
31+
print(json.dumps({"function":"timedelta","mean_ms":round(total_ms/ITERATIONS,3),"iterations":ITERATIONS,"total_ms":round(total_ms,3)}))
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
"""Benchmark: Timestamp — construction and component accessors."""
2+
import json, time
3+
import pandas as pd
4+
from datetime import datetime, timezone, timedelta
5+
6+
SIZE = 10_000
7+
WARMUP = 5
8+
ITERATIONS = 50
9+
10+
base = datetime(2020, 1, 1, tzinfo=timezone.utc)
11+
dates = [base + timedelta(days=i) for i in range(SIZE)]
12+
13+
for _ in range(WARMUP):
14+
for d in dates:
15+
ts = pd.Timestamp(d)
16+
_ = ts.year
17+
_ = ts.month
18+
_ = ts.dayofweek
19+
20+
times = []
21+
for _ in range(ITERATIONS):
22+
t0 = time.perf_counter()
23+
for d in dates:
24+
ts = pd.Timestamp(d)
25+
_ = ts.year
26+
_ = ts.month
27+
_ = ts.dayofweek
28+
times.append((time.perf_counter() - t0) * 1000)
29+
30+
total_ms = sum(times)
31+
print(json.dumps({"function":"timestamp","mean_ms":round(total_ms/ITERATIONS,3),"iterations":ITERATIONS,"total_ms":round(total_ms,3)}))
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/**
2+
* Benchmark: astypeSeries — cast Series dtype.
3+
* Outputs JSON: {"function": "astype_series", "mean_ms": ..., "iterations": ..., "total_ms": ...}
4+
*/
5+
import { Series, astypeSeries } from "../../src/index.ts";
6+
7+
const SIZE = 100_000;
8+
const WARMUP = 5;
9+
const ITERATIONS = 50;
10+
11+
const floatSeries = new Series(Array.from({ length: SIZE }, (_, i) => i * 1.5));
12+
const intSeries = new Series(Array.from({ length: SIZE }, (_, i) => i));
13+
14+
for (let i = 0; i < WARMUP; i++) {
15+
astypeSeries(floatSeries, "int32");
16+
astypeSeries(intSeries, "float64");
17+
astypeSeries(intSeries, "string");
18+
}
19+
20+
const times: number[] = [];
21+
for (let i = 0; i < ITERATIONS; i++) {
22+
const start = performance.now();
23+
astypeSeries(floatSeries, "int32");
24+
astypeSeries(intSeries, "float64");
25+
astypeSeries(intSeries, "string");
26+
times.push(performance.now() - start);
27+
}
28+
29+
const totalMs = times.reduce((a, b) => a + b, 0);
30+
const meanMs = totalMs / ITERATIONS;
31+
console.log(
32+
JSON.stringify({
33+
function: "astype_series",
34+
mean_ms: Math.round(meanMs * 1000) / 1000,
35+
iterations: ITERATIONS,
36+
total_ms: Math.round(totalMs * 1000) / 1000,
37+
}),
38+
);
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/**
2+
* Benchmark: DateOffset — MonthEnd, BusinessDay, YearBegin apply.
3+
* Outputs JSON: {"function": "date_offset", "mean_ms": ..., "iterations": ..., "total_ms": ...}
4+
*/
5+
import { MonthEnd, BusinessDay, YearBegin, Day } from "../../src/index.ts";
6+
7+
const SIZE = 10_000;
8+
const WARMUP = 5;
9+
const ITERATIONS = 50;
10+
11+
const monthEnd = new MonthEnd(1);
12+
const bizDay = new BusinessDay(5);
13+
const yearBegin = new YearBegin(1);
14+
const dayOffset = new Day(30);
15+
const base = new Date(Date.UTC(2020, 0, 15));
16+
const dates = Array.from({ length: SIZE }, (_, i) => new Date(base.getTime() + i * 86_400_000));
17+
18+
for (let i = 0; i < WARMUP; i++) {
19+
for (const d of dates) {
20+
monthEnd.apply(d);
21+
bizDay.apply(d);
22+
yearBegin.apply(d);
23+
dayOffset.apply(d);
24+
}
25+
}
26+
27+
const times: number[] = [];
28+
for (let i = 0; i < ITERATIONS; i++) {
29+
const start = performance.now();
30+
for (const d of dates) {
31+
monthEnd.apply(d);
32+
bizDay.apply(d);
33+
yearBegin.apply(d);
34+
dayOffset.apply(d);
35+
}
36+
times.push(performance.now() - start);
37+
}
38+
39+
const totalMs = times.reduce((a, b) => a + b, 0);
40+
const meanMs = totalMs / ITERATIONS;
41+
console.log(
42+
JSON.stringify({
43+
function: "date_offset",
44+
mean_ms: Math.round(meanMs * 1000) / 1000,
45+
iterations: ITERATIONS,
46+
total_ms: Math.round(totalMs * 1000) / 1000,
47+
}),
48+
);

0 commit comments

Comments
 (0)