Skip to content

Commit 7d019b0

Browse files
authored
Merge pull request #147 from githubnext/autoloop/perf-comparison
[Autoloop] [Autoloop: perf-comparison]
2 parents a5e0b23 + 5b7ea6d commit 7d019b0

256 files changed

Lines changed: 9917 additions & 0 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
"""
2+
Benchmark: DataFrame.align — align two 10k-row DataFrames on inner/outer/left join.
3+
Outputs JSON: {"function": "align_dataframe", "mean_ms": ..., "iterations": ..., "total_ms": ...}
4+
"""
5+
import json
6+
import time
7+
import numpy as np
8+
import pandas as pd
9+
10+
SIZE = 10_000
11+
WARMUP = 5
12+
ITERATIONS = 30
13+
14+
idx_a = [i * 2 for i in range(SIZE)]
15+
idx_b = [i * 3 for i in range(SIZE)]
16+
17+
df_a = pd.DataFrame(
18+
{"x": [i * 1.0 for i in range(SIZE)], "y": [i * 2.0 for i in range(SIZE)], "z": [i * 3.0 for i in range(SIZE)]},
19+
index=idx_a,
20+
)
21+
df_b = pd.DataFrame(
22+
{"y": [i * 10.0 for i in range(SIZE)], "z": [i * 20.0 for i in range(SIZE)], "w": [i * 30.0 for i in range(SIZE)]},
23+
index=idx_b,
24+
)
25+
26+
for _ in range(WARMUP):
27+
df_a.align(df_b, join="inner")
28+
df_a.align(df_b, join="outer")
29+
df_a.align(df_b, join="left")
30+
31+
start = time.perf_counter()
32+
for _ in range(ITERATIONS):
33+
df_a.align(df_b, join="inner")
34+
df_a.align(df_b, join="outer")
35+
df_a.align(df_b, join="left")
36+
total = (time.perf_counter() - start) * 1000
37+
38+
print(json.dumps({
39+
"function": "align_dataframe",
40+
"mean_ms": total / ITERATIONS,
41+
"iterations": ITERATIONS,
42+
"total_ms": total,
43+
}))
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
"""
2+
Benchmark: Series.align — align two 50k-element Series on inner/outer/left join.
3+
Outputs JSON: {"function": "align_series", "mean_ms": ..., "iterations": ..., "total_ms": ...}
4+
"""
5+
import json
6+
import time
7+
import numpy as np
8+
import pandas as pd
9+
10+
SIZE = 50_000
11+
WARMUP = 5
12+
ITERATIONS = 30
13+
14+
idx_a = [i * 2 for i in range(SIZE)]
15+
idx_b = [i * 3 for i in range(SIZE)]
16+
s_a = pd.Series([i * 1.0 for i in range(SIZE)], index=idx_a)
17+
s_b = pd.Series([i * 2.0 for i in range(SIZE)], index=idx_b)
18+
19+
for _ in range(WARMUP):
20+
s_a.align(s_b, join="inner")
21+
s_a.align(s_b, join="outer")
22+
s_a.align(s_b, join="left")
23+
24+
start = time.perf_counter()
25+
for _ in range(ITERATIONS):
26+
s_a.align(s_b, join="inner")
27+
s_a.align(s_b, join="outer")
28+
s_a.align(s_b, join="left")
29+
total = (time.perf_counter() - start) * 1000
30+
31+
print(json.dumps({
32+
"function": "align_series",
33+
"mean_ms": total / ITERATIONS,
34+
"iterations": ITERATIONS,
35+
"total_ms": total,
36+
}))
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: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
"""
2+
Benchmark: pd.bdate_range — generate business-day DatetimeIndex with 1000 periods.
3+
Outputs JSON: {"function": "bdate_range", "mean_ms": ..., "iterations": ..., "total_ms": ...}
4+
"""
5+
import json
6+
import time
7+
import pandas as pd
8+
9+
WARMUP = 5
10+
ITERATIONS = 100
11+
12+
for _ in range(WARMUP):
13+
pd.bdate_range(start="2020-01-01", periods=1000)
14+
15+
start = time.perf_counter()
16+
for _ in range(ITERATIONS):
17+
pd.bdate_range(start="2020-01-01", periods=1000)
18+
total = (time.perf_counter() - start) * 1000
19+
20+
print(json.dumps({
21+
"function": "bdate_range",
22+
"mean_ms": total / ITERATIONS,
23+
"iterations": ITERATIONS,
24+
"total_ms": total,
25+
}))
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
"""
2+
Benchmark: Python type coercion equivalents — int(), float(), str(), bool() conversions.
3+
Outputs JSON: {"function": "cast_scalar", "mean_ms": ..., "iterations": ..., "total_ms": ...}
4+
"""
5+
import json
6+
import time
7+
8+
SIZE = 100_000
9+
WARMUP = 5
10+
ITERATIONS = 50
11+
12+
int_values = [i % 1000 for i in range(SIZE)]
13+
float_values = [i * 0.5 for i in range(SIZE)]
14+
str_values = [str(i % 1000) for i in range(SIZE)]
15+
bool_values = [i % 2 == 0 for i in range(SIZE)]
16+
17+
for _ in range(WARMUP):
18+
for j in range(SIZE):
19+
int(float_values[j])
20+
float(int_values[j])
21+
int(str_values[j])
22+
int(bool_values[j])
23+
24+
times = []
25+
for _ in range(ITERATIONS):
26+
t0 = time.perf_counter()
27+
for j in range(SIZE):
28+
int(float_values[j])
29+
float(int_values[j])
30+
int(str_values[j])
31+
int(bool_values[j])
32+
times.append((time.perf_counter() - t0) * 1000)
33+
34+
total_ms = sum(times)
35+
mean_ms = total_ms / ITERATIONS
36+
print(json.dumps({"function": "cast_scalar", "mean_ms": round(mean_ms, 3), "iterations": ITERATIONS, "total_ms": round(total_ms, 3)}))
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
"""
2+
Benchmark: pd.Categorical.codes / categories / ordered — category accessor properties
3+
on a 100k-element categorical Series.
4+
Outputs JSON: {"function": "cat_codes_accessor", "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+
CATS = 50
13+
WARMUP = 5
14+
ITERATIONS = 30
15+
16+
categories = [f"cat_{i}" for i in range(CATS)]
17+
data = [categories[i % CATS] for i in range(SIZE)]
18+
s = pd.Categorical(data, categories=categories)
19+
ps = pd.Series(s)
20+
21+
for _ in range(WARMUP):
22+
_ = ps.cat.codes
23+
_ = ps.cat.categories
24+
_ = ps.cat.ordered
25+
_ = len(ps.cat.categories)
26+
27+
times = []
28+
for _ in range(ITERATIONS):
29+
t0 = time.perf_counter()
30+
_ = ps.cat.codes
31+
_ = ps.cat.categories
32+
_ = ps.cat.ordered
33+
_ = len(ps.cat.categories)
34+
times.append((time.perf_counter() - t0) * 1000)
35+
36+
total_ms = sum(times)
37+
print(json.dumps({
38+
"function": "cat_codes_accessor",
39+
"mean_ms": round(total_ms / ITERATIONS, 3),
40+
"iterations": ITERATIONS,
41+
"total_ms": round(total_ms, 3),
42+
}))
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
"""
2+
Benchmark: pandas.CategoricalIndex — creation, get_loc, add_categories, set operations on 100k elements.
3+
Outputs JSON: {"function": "categorical_index", "mean_ms": ..., "iterations": ..., "total_ms": ...}
4+
"""
5+
import json
6+
import time
7+
import numpy as np
8+
import pandas as pd
9+
10+
SIZE = 100_000
11+
WARMUP = 5
12+
ITERATIONS = 30
13+
14+
CATS = ["alpha", "beta", "gamma", "delta", "epsilon"]
15+
labels = [CATS[i % len(CATS)] for i in range(SIZE)]
16+
ci = pd.CategoricalIndex(labels)
17+
labels2 = [CATS[(i + 2) % len(CATS)] for i in range(SIZE // 2)]
18+
ci2 = pd.CategoricalIndex(labels2)
19+
20+
for _ in range(WARMUP):
21+
pd.CategoricalIndex(labels)
22+
ci.get_loc("beta")
23+
ci.add_categories(["zeta"])
24+
ci.union(ci2)
25+
ci.intersection(ci2)
26+
27+
start = time.perf_counter()
28+
for _ in range(ITERATIONS):
29+
pd.CategoricalIndex(labels)
30+
ci.get_loc("beta")
31+
ci.add_categories(["zeta"])
32+
ci.union(ci2)
33+
ci.intersection(ci2)
34+
total = (time.perf_counter() - start) * 1000
35+
36+
print(json.dumps({
37+
"function": "categorical_index",
38+
"mean_ms": total / ITERATIONS,
39+
"iterations": ITERATIONS,
40+
"total_ms": total,
41+
}))
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
"""
2+
Benchmark: Series.clip(lower=, upper=) / DataFrame.clip(lower=, upper=) — element-wise clip bounds.
3+
Outputs JSON: {"function": "clip_series_bounds", "mean_ms": ..., "iterations": ..., "total_ms": ...}
4+
"""
5+
import json
6+
import time
7+
import numpy as np
8+
import pandas as pd
9+
10+
SIZE = 100_000
11+
WARMUP = 5
12+
ITERATIONS = 50
13+
14+
data = np.arange(SIZE) - SIZE / 2
15+
s = pd.Series(data)
16+
lower_s = pd.Series(np.full(SIZE, -10000.0))
17+
upper_s = pd.Series(np.full(SIZE, 10000.0))
18+
19+
df = pd.DataFrame({
20+
"a": np.arange(SIZE) - SIZE / 2,
21+
"b": np.sin(np.arange(SIZE) * 0.01) * 100,
22+
})
23+
lower_df = pd.DataFrame({"a": np.full(SIZE, -10000.0), "b": np.full(SIZE, -50.0)})
24+
upper_df = pd.DataFrame({"a": np.full(SIZE, 10000.0), "b": np.full(SIZE, 50.0)})
25+
26+
for _ in range(WARMUP):
27+
s.clip(lower=lower_s, upper=upper_s)
28+
df.clip(lower=lower_df, upper=upper_df)
29+
30+
start = time.perf_counter()
31+
for _ in range(ITERATIONS):
32+
s.clip(lower=lower_s, upper=upper_s)
33+
df.clip(lower=lower_df, upper=upper_df)
34+
total = (time.perf_counter() - start) * 1000
35+
36+
print(json.dumps({
37+
"function": "clip_series_bounds",
38+
"mean_ms": total / ITERATIONS,
39+
"iterations": ITERATIONS,
40+
"total_ms": total,
41+
}))
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
"""Benchmark: DataFrame.combine_first — fill NaN values from another DataFrame (union of indexes).
2+
Mirrors tsb bench_combine_first_dataframe.ts.
3+
"""
4+
import json, time
5+
import numpy as np
6+
import pandas as pd
7+
8+
SIZE = 5_000
9+
WARMUP = 5
10+
ITERATIONS = 30
11+
12+
rows1 = list(range(SIZE))
13+
data1a = [None if i % 3 == 0 else i * 1.5 for i in range(SIZE)]
14+
data1b = [None if i % 5 == 0 else i * 0.5 for i in range(SIZE)]
15+
df1 = pd.DataFrame({"a": data1a, "b": data1b}, index=rows1)
16+
17+
rows2 = list(range(SIZE + 500))
18+
data2a = [i * 2.0 for i in range(SIZE + 500)]
19+
data2b = [i * 1.0 for i in range(SIZE + 500)]
20+
data2c = [i * 0.1 for i in range(SIZE + 500)]
21+
df2 = pd.DataFrame({"a": data2a, "b": data2b, "c": data2c}, index=rows2)
22+
23+
for _ in range(WARMUP):
24+
df1.combine_first(df2)
25+
26+
start = time.perf_counter()
27+
for _ in range(ITERATIONS):
28+
df1.combine_first(df2)
29+
total = (time.perf_counter() - start) * 1000
30+
31+
print(json.dumps({
32+
"function": "combine_first_dataframe",
33+
"mean_ms": round(total / ITERATIONS, 3),
34+
"iterations": ITERATIONS,
35+
"total_ms": round(total, 3),
36+
}))
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
"""
2+
Benchmark: pandas concat with join="inner" and ignore_index=True options.
3+
Outputs JSON: {"function": "concat_options", "mean_ms": ..., "iterations": ..., "total_ms": ...}
4+
"""
5+
import json
6+
import time
7+
import pandas as pd
8+
9+
ROWS = 50_000
10+
WARMUP = 5
11+
ITERATIONS = 20
12+
13+
df1 = pd.DataFrame({
14+
"a": [i * 1.0 for i in range(ROWS)],
15+
"b": [i * 2.0 for i in range(ROWS)],
16+
"c": [i * 3.0 for i in range(ROWS)],
17+
})
18+
df2 = pd.DataFrame({
19+
"a": [i * 1.5 for i in range(ROWS)],
20+
"b": [i * 2.5 for i in range(ROWS)],
21+
"d": [i * 4.0 for i in range(ROWS)],
22+
})
23+
24+
for _ in range(WARMUP):
25+
pd.concat([df1, df2], join="inner", ignore_index=True)
26+
pd.concat([df1, df2], join="outer", ignore_index=True)
27+
28+
times = []
29+
for _ in range(ITERATIONS):
30+
t0 = time.perf_counter()
31+
pd.concat([df1, df2], join="inner", ignore_index=True)
32+
pd.concat([df1, df2], join="outer", ignore_index=True)
33+
times.append((time.perf_counter() - t0) * 1000)
34+
35+
total_ms = sum(times)
36+
mean_ms = total_ms / ITERATIONS
37+
print(json.dumps({"function": "concat_options", "mean_ms": round(mean_ms, 3), "iterations": ITERATIONS, "total_ms": round(total_ms, 3)}))

0 commit comments

Comments
 (0)