Skip to content

Commit bae766a

Browse files
Iteration 139: Add 8 benchmark pairs (420 total, +8 vs 412)
Added benchmark pairs: - cut_interval_index: cutIntervalIndex/qcutIntervalIndex vs pd.cut/qcut - dataframe_sign: dataFrameSign vs np.sign(df) - argsort_scalars: argsortScalars/searchsortedMany vs np.argsort/searchsorted - interval_index_ops: IntervalIndex.contains/get_loc vs pd.IntervalIndex ops - period_index_range: PeriodIndex.periodRange/fromPeriods vs pd.period_range - datetime_index_from: DatetimeIndex.fromDates/fromTimestamps vs pd.DatetimeIndex - timedelta_index: TimedeltaIndex.fromTimedeltas/fromRange/fromStrings vs pd.TimedeltaIndex - resolve_freq: resolveFreq vs pd.tseries.frequencies.to_offset Run: https://github.com/githubnext/tsessebe/actions/runs/24539911725 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 26437c0 commit bae766a

16 files changed

Lines changed: 500 additions & 0 deletions
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
"""Benchmark: np.argsort / np.searchsorted — sort/search utilities on 100k-element arrays."""
2+
import json
3+
import time
4+
import numpy as np
5+
6+
SIZE = 100_000
7+
WARMUP = 3
8+
ITERATIONS = 20
9+
10+
arr = np.sin(np.arange(SIZE) * 0.001) * SIZE
11+
sorted_arr = np.sort(arr)
12+
queries = (np.arange(1000) - 500) * SIZE / 500
13+
14+
for _ in range(WARMUP):
15+
np.argsort(arr)
16+
np.searchsorted(sorted_arr, queries)
17+
18+
start = time.perf_counter()
19+
for _ in range(ITERATIONS):
20+
np.argsort(arr)
21+
np.searchsorted(sorted_arr, queries)
22+
total = (time.perf_counter() - start) * 1000
23+
24+
print(json.dumps({"function": "argsort_scalars", "mean_ms": total / ITERATIONS, "iterations": ITERATIONS, "total_ms": total}))
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
"""Benchmark: cutIntervalIndex / qcutIntervalIndex — pd.cut/qcut returning IntervalIndex on 100k-element Series."""
2+
import json
3+
import time
4+
import numpy as np
5+
import pandas as pd
6+
7+
SIZE = 100_000
8+
WARMUP = 5
9+
ITERATIONS = 30
10+
11+
data = (np.arange(SIZE) % 1000) * 0.1
12+
s = pd.Series(data)
13+
14+
for _ in range(WARMUP):
15+
pd.cut(s, 20, retbins=False)
16+
pd.qcut(s, 10, duplicates="drop")
17+
18+
start = time.perf_counter()
19+
for _ in range(ITERATIONS):
20+
pd.cut(s, 20, retbins=False)
21+
pd.qcut(s, 10, duplicates="drop")
22+
total = (time.perf_counter() - start) * 1000
23+
24+
print(json.dumps({"function": "cut_interval_index", "mean_ms": total / ITERATIONS, "iterations": ITERATIONS, "total_ms": total}))
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
"""Benchmark: DataFrame sign operation — np.sign on 100k-row DataFrame."""
2+
import json
3+
import time
4+
import numpy as np
5+
import pandas as pd
6+
7+
ROWS = 100_000
8+
WARMUP = 5
9+
ITERATIONS = 50
10+
11+
df = pd.DataFrame({
12+
"a": (np.arange(ROWS) % 200) - 100,
13+
"b": np.sin(np.arange(ROWS) * 0.01) * 1000,
14+
"c": (np.arange(ROWS) % 3) - 1,
15+
})
16+
17+
for _ in range(WARMUP):
18+
np.sign(df)
19+
20+
start = time.perf_counter()
21+
for _ in range(ITERATIONS):
22+
np.sign(df)
23+
total = (time.perf_counter() - start) * 1000
24+
25+
print(json.dumps({"function": "dataframe_sign", "mean_ms": total / ITERATIONS, "iterations": ITERATIONS, "total_ms": total}))
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
"""Benchmark: pd.DatetimeIndex from dates/timestamps — DatetimeIndex construction from raw data."""
2+
import json
3+
import time
4+
import numpy as np
5+
import pandas as pd
6+
7+
SIZE = 10_000
8+
WARMUP = 5
9+
ITERATIONS = 50
10+
11+
base = pd.Timestamp("2000-01-01")
12+
dates = [base + pd.Timedelta(days=i) for i in range(SIZE)]
13+
timestamps = np.arange(SIZE) * 86_400 * 1_000_000_000 + base.value # nanosecond timestamps
14+
15+
for _ in range(WARMUP):
16+
pd.DatetimeIndex(dates)
17+
pd.DatetimeIndex(timestamps)
18+
19+
start = time.perf_counter()
20+
for _ in range(ITERATIONS):
21+
pd.DatetimeIndex(dates)
22+
pd.DatetimeIndex(timestamps)
23+
total = (time.perf_counter() - start) * 1000
24+
25+
print(json.dumps({"function": "datetime_index_from", "mean_ms": total / ITERATIONS, "iterations": ITERATIONS, "total_ms": total}))
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
"""Benchmark: IntervalIndex contains / get_loc — interval index lookup ops on 1k-interval index."""
2+
import json
3+
import time
4+
import numpy as np
5+
import pandas as pd
6+
7+
BREAKS = 1_001 # 1000 intervals
8+
QUERIES = 10_000
9+
WARMUP = 5
10+
ITERATIONS = 50
11+
12+
breaks = np.arange(BREAKS) * 0.1
13+
idx = pd.IntervalIndex.from_breaks(breaks)
14+
15+
# Query values spread across the range
16+
query_values = (np.arange(QUERIES) / QUERIES) * (BREAKS - 1) * 0.1
17+
18+
for _ in range(WARMUP):
19+
for q in query_values[:100]:
20+
idx.contains(q)
21+
idx.get_loc(q)
22+
23+
start = time.perf_counter()
24+
for _ in range(ITERATIONS):
25+
for q in query_values:
26+
idx.contains(q)
27+
idx.get_loc(q)
28+
total = (time.perf_counter() - start) * 1000
29+
30+
print(json.dumps({"function": "interval_index_ops", "mean_ms": total / ITERATIONS, "iterations": ITERATIONS, "total_ms": total}))
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
"""Benchmark: pd.period_range / pd.PeriodIndex — PeriodIndex construction."""
2+
import json
3+
import time
4+
import pandas as pd
5+
6+
WARMUP = 5
7+
ITERATIONS = 50
8+
9+
start_d = pd.Period("2000-01-01", freq="D")
10+
start_m = pd.Period("2000-01", freq="M")
11+
day_periods = pd.period_range(start="2000-01-01", periods=365 * 10, freq="D")
12+
13+
for _ in range(WARMUP):
14+
pd.period_range(start=start_d, periods=3650, freq="D")
15+
pd.period_range(start=start_m, periods=120, freq="ME")
16+
pd.PeriodIndex(day_periods[:365])
17+
18+
start = time.perf_counter()
19+
for _ in range(ITERATIONS):
20+
pd.period_range(start=start_d, periods=3650, freq="D")
21+
pd.period_range(start=start_m, periods=120, freq="ME")
22+
pd.PeriodIndex(day_periods[:365])
23+
total = (time.perf_counter() - start) * 1000
24+
25+
print(json.dumps({"function": "period_index_range", "mean_ms": total / ITERATIONS, "iterations": ITERATIONS, "total_ms": total}))
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
"""Benchmark: pd.tseries.frequencies.to_offset — frequency string-to-offset resolution."""
2+
import json
3+
import time
4+
import pandas as pd
5+
from pandas.tseries.frequencies import to_offset
6+
7+
WARMUP = 5
8+
ITERATIONS = 1_000
9+
10+
freqs = ["D", "h", "min", "s", "ms", "ME", "QE", "YE", "W", "B"]
11+
12+
for _ in range(WARMUP):
13+
for f in freqs:
14+
to_offset(f)
15+
to_offset(f"2{f}")
16+
17+
start = time.perf_counter()
18+
for _ in range(ITERATIONS):
19+
for f in freqs:
20+
to_offset(f)
21+
to_offset(f"2{f}")
22+
total = (time.perf_counter() - start) * 1000
23+
24+
print(json.dumps({"function": "resolve_freq", "mean_ms": total / ITERATIONS, "iterations": ITERATIONS, "total_ms": total}))
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
"""Benchmark: pd.TimedeltaIndex construction from timedeltas/range/strings."""
2+
import json
3+
import time
4+
import numpy as np
5+
import pandas as pd
6+
7+
SIZE = 1_000
8+
WARMUP = 5
9+
ITERATIONS = 100
10+
11+
deltas = [pd.Timedelta(days=i, hours=i % 24) for i in range(SIZE)]
12+
start_td = pd.Timedelta(days=0)
13+
stop_td = pd.Timedelta(days=SIZE)
14+
step_td = pd.Timedelta(days=1)
15+
strings = [f"{i}D" for i in range(SIZE)]
16+
17+
for _ in range(WARMUP):
18+
pd.TimedeltaIndex(deltas)
19+
pd.timedelta_range(start=start_td, end=stop_td, freq=step_td)
20+
pd.to_timedelta(strings)
21+
22+
start = time.perf_counter()
23+
for _ in range(ITERATIONS):
24+
pd.TimedeltaIndex(deltas)
25+
pd.timedelta_range(start=start_td, end=stop_td, freq=step_td)
26+
pd.to_timedelta(strings)
27+
total = (time.perf_counter() - start) * 1000
28+
29+
print(json.dumps({"function": "timedelta_index", "mean_ms": total / ITERATIONS, "iterations": ITERATIONS, "total_ms": total}))
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/**
2+
* Benchmark: argsortScalars / searchsortedMany — sort/search utilities on 100k-element arrays.
3+
* Outputs JSON: {"function": "argsort_scalars", "mean_ms": ..., "iterations": ..., "total_ms": ...}
4+
*/
5+
import { argsortScalars, searchsortedMany } from "../../src/index.ts";
6+
7+
const SIZE = 100_000;
8+
const WARMUP = 3;
9+
const ITERATIONS = 20;
10+
11+
// Array of numbers to sort/search
12+
const arr = Array.from({ length: SIZE }, (_, i) => Math.sin(i * 0.001) * SIZE);
13+
// Sorted version for searchsortedMany
14+
const sorted = [...arr].sort((a, b) => (a as number) - (b as number));
15+
// Query values for searchsortedMany
16+
const queries = Array.from({ length: 1000 }, (_, i) => (i - 500) * SIZE / 500);
17+
18+
for (let i = 0; i < WARMUP; i++) {
19+
argsortScalars(arr);
20+
searchsortedMany(sorted, queries);
21+
}
22+
23+
const start = performance.now();
24+
for (let i = 0; i < ITERATIONS; i++) {
25+
argsortScalars(arr);
26+
searchsortedMany(sorted, queries);
27+
}
28+
const total = performance.now() - start;
29+
30+
console.log(
31+
JSON.stringify({
32+
function: "argsort_scalars",
33+
mean_ms: total / ITERATIONS,
34+
iterations: ITERATIONS,
35+
total_ms: total,
36+
}),
37+
);
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/**
2+
* Benchmark: cutIntervalIndex / qcutIntervalIndex — cut/qcut returning IntervalIndex on 100k-element Series.
3+
* Outputs JSON: {"function": "cut_interval_index", "mean_ms": ..., "iterations": ..., "total_ms": ...}
4+
*/
5+
import { Series, cutIntervalIndex, qcutIntervalIndex } from "../../src/index.ts";
6+
7+
const SIZE = 100_000;
8+
const WARMUP = 5;
9+
const ITERATIONS = 30;
10+
11+
const data = Array.from({ length: SIZE }, (_, i) => (i % 1000) * 0.1);
12+
const s = new Series({ data });
13+
14+
for (let i = 0; i < WARMUP; i++) {
15+
cutIntervalIndex(s, 20);
16+
qcutIntervalIndex(s, 10);
17+
}
18+
19+
const start = performance.now();
20+
for (let i = 0; i < ITERATIONS; i++) {
21+
cutIntervalIndex(s, 20);
22+
qcutIntervalIndex(s, 10);
23+
}
24+
const total = performance.now() - start;
25+
26+
console.log(
27+
JSON.stringify({
28+
function: "cut_interval_index",
29+
mean_ms: total / ITERATIONS,
30+
iterations: ITERATIONS,
31+
total_ms: total,
32+
}),
33+
);

0 commit comments

Comments
 (0)