Skip to content

Commit b854980

Browse files
Iteration 147: Add 8 benchmark pairs (462 total, +2 vs best 460)
Added 8 new benchmark pairs covering: - timestamp_arith: Timestamp.add/sub/eq/lt/gt/le/ge/ne operations - timestamp_str_format: strftime/isoformat/day_name/month_name - timestamp_round_normalize: ceil/floor/round/normalize - value_counts_opts: valueCounts with normalize/ascending/dropna options - series_sortvalues_opts: Series.sortValues with ascending=false/naPosition='first' - dataframe_sortvalues_mixed: DataFrame.sortValues with mixed ascending array - series_groupby_size: SeriesGroupBy.size() and getGroup() - series_log_natural: seriesLog (natural logarithm) Run: https://github.com/githubnext/tsessebe/actions/runs/24555921452 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 8568c4a commit b854980

16 files changed

Lines changed: 597 additions & 0 deletions
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
"""Benchmark: DataFrame.sort_values with mixed ascending list [True, False, True]."""
2+
import json
3+
import time
4+
import pandas as pd
5+
import numpy as np
6+
7+
ROWS = 100_000
8+
WARMUP = 3
9+
ITERATIONS = 20
10+
11+
df = pd.DataFrame({
12+
"category": [f"group_{i % 10}" for i in range(ROWS)],
13+
"priority": [i % 5 for i in range(ROWS)],
14+
"value": np.random.random(ROWS) * 1000,
15+
})
16+
17+
for _ in range(WARMUP):
18+
df.sort_values(["category", "priority", "value"], ascending=[True, False, True])
19+
df.sort_values(["category", "value"], ascending=[False, True])
20+
21+
start = time.perf_counter()
22+
for _ in range(ITERATIONS):
23+
df.sort_values(["category", "priority", "value"], ascending=[True, False, True])
24+
df.sort_values(["category", "value"], ascending=[False, True])
25+
total = (time.perf_counter() - start) * 1000
26+
27+
print(json.dumps({
28+
"function": "dataframe_sortvalues_mixed",
29+
"mean_ms": total / ITERATIONS,
30+
"iterations": ITERATIONS,
31+
"total_ms": total,
32+
}))
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
"""Benchmark: SeriesGroupBy.size() and get_group() operations."""
2+
import json
3+
import time
4+
import pandas as pd
5+
import numpy as np
6+
7+
ROWS = 100_000
8+
WARMUP = 3
9+
ITERATIONS = 20
10+
11+
values = pd.Series(np.random.random(ROWS) * 1000)
12+
groups = pd.Series([f"g{i % 20}" for i in range(ROWS)])
13+
14+
for _ in range(WARMUP):
15+
values.groupby(groups).size()
16+
values.groupby(groups).get_group("g0")
17+
values.groupby(groups).get_group("g10")
18+
19+
start = time.perf_counter()
20+
for _ in range(ITERATIONS):
21+
values.groupby(groups).size()
22+
values.groupby(groups).get_group("g0")
23+
values.groupby(groups).get_group("g10")
24+
total = (time.perf_counter() - start) * 1000
25+
26+
print(json.dumps({
27+
"function": "series_groupby_size",
28+
"mean_ms": total / ITERATIONS,
29+
"iterations": ITERATIONS,
30+
"total_ms": total,
31+
}))
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
"""Benchmark: Series natural logarithm — np.log / Series.apply(np.log) on 100k-element Series."""
2+
import json
3+
import time
4+
import pandas as pd
5+
import numpy as np
6+
7+
ROWS = 100_000
8+
WARMUP = 5
9+
ITERATIONS = 50
10+
11+
s = pd.Series(np.arange(1, ROWS + 1, dtype=float))
12+
13+
for _ in range(WARMUP):
14+
np.log(s)
15+
16+
start = time.perf_counter()
17+
for _ in range(ITERATIONS):
18+
np.log(s)
19+
total = (time.perf_counter() - start) * 1000
20+
21+
print(json.dumps({
22+
"function": "series_log_natural",
23+
"mean_ms": total / ITERATIONS,
24+
"iterations": ITERATIONS,
25+
"total_ms": total,
26+
}))
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
"""Benchmark: Series.sort_values with options — ascending=False, na_position='first'."""
2+
import json
3+
import time
4+
import pandas as pd
5+
import numpy as np
6+
7+
ROWS = 100_000
8+
WARMUP = 3
9+
ITERATIONS = 20
10+
11+
data = [None if i % 1000 == 0 else (np.random.random() * 10000 - 5000) for i in range(ROWS)]
12+
s = pd.Series(data)
13+
14+
for _ in range(WARMUP):
15+
s.sort_values(ascending=False)
16+
s.sort_values(ascending=True, na_position="first")
17+
s.sort_values(ascending=False, na_position="first")
18+
19+
start = time.perf_counter()
20+
for _ in range(ITERATIONS):
21+
s.sort_values(ascending=False)
22+
s.sort_values(ascending=True, na_position="first")
23+
s.sort_values(ascending=False, na_position="first")
24+
total = (time.perf_counter() - start) * 1000
25+
26+
print(json.dumps({
27+
"function": "series_sortvalues_opts",
28+
"mean_ms": total / ITERATIONS,
29+
"iterations": ITERATIONS,
30+
"total_ms": total,
31+
}))
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
"""Benchmark: Timestamp arithmetic — add timedelta, subtract, comparison operators."""
2+
import json
3+
import time
4+
import pandas as pd
5+
from datetime import timedelta
6+
7+
SIZE = 10_000
8+
WARMUP = 5
9+
ITERATIONS = 50
10+
11+
base = pd.Timestamp("2024-01-01")
12+
timestamps = [pd.Timestamp("2020-01-01") + timedelta(days=i) for i in range(SIZE)]
13+
delta = pd.Timedelta(days=30)
14+
delta2 = pd.Timedelta(hours=12)
15+
16+
for _ in range(WARMUP):
17+
for ts in timestamps:
18+
ts + delta
19+
ts - delta2
20+
ts == base
21+
ts < base
22+
ts > base
23+
ts <= base
24+
ts >= base
25+
ts != base
26+
27+
start = time.perf_counter()
28+
for _ in range(ITERATIONS):
29+
for ts in timestamps:
30+
ts + delta
31+
ts - delta2
32+
ts == base
33+
ts < base
34+
ts > base
35+
ts <= base
36+
ts >= base
37+
ts != base
38+
total = (time.perf_counter() - start) * 1000
39+
40+
print(json.dumps({
41+
"function": "timestamp_arith",
42+
"mean_ms": total / ITERATIONS,
43+
"iterations": ITERATIONS,
44+
"total_ms": total,
45+
}))
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
"""Benchmark: Timestamp rounding — floor, ceil, round, normalize."""
2+
import json
3+
import time
4+
import pandas as pd
5+
6+
SIZE = 10_000
7+
WARMUP = 5
8+
ITERATIONS = 50
9+
10+
timestamps = [
11+
pd.Timestamp(year=2020, month=(i % 12) + 1, day=(i % 28) + 1,
12+
hour=i % 24, minute=(i * 7) % 60, second=(i * 13) % 60)
13+
for i in range(SIZE)
14+
]
15+
16+
for _ in range(WARMUP):
17+
for ts in timestamps:
18+
ts.floor("h")
19+
ts.ceil("h")
20+
ts.round("min")
21+
ts.normalize()
22+
23+
start = time.perf_counter()
24+
for _ in range(ITERATIONS):
25+
for ts in timestamps:
26+
ts.floor("h")
27+
ts.ceil("h")
28+
ts.round("min")
29+
ts.normalize()
30+
total = (time.perf_counter() - start) * 1000
31+
32+
print(json.dumps({
33+
"function": "timestamp_round_normalize",
34+
"mean_ms": total / ITERATIONS,
35+
"iterations": ITERATIONS,
36+
"total_ms": total,
37+
}))
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
"""Benchmark: Timestamp string formatting — strftime, isoformat, day_name, month_name."""
2+
import json
3+
import time
4+
import pandas as pd
5+
6+
SIZE = 10_000
7+
WARMUP = 5
8+
ITERATIONS = 50
9+
10+
timestamps = [
11+
pd.Timestamp(year=2020, month=(i % 12) + 1, day=(i % 28) + 1,
12+
hour=i % 24, minute=i % 60, second=i % 60)
13+
for i in range(SIZE)
14+
]
15+
16+
for _ in range(WARMUP):
17+
for ts in timestamps:
18+
ts.strftime("%Y-%m-%d %H:%M:%S")
19+
ts.isoformat()
20+
ts.day_name()
21+
ts.month_name()
22+
23+
start = time.perf_counter()
24+
for _ in range(ITERATIONS):
25+
for ts in timestamps:
26+
ts.strftime("%Y-%m-%d %H:%M:%S")
27+
ts.isoformat()
28+
ts.day_name()
29+
ts.month_name()
30+
total = (time.perf_counter() - start) * 1000
31+
32+
print(json.dumps({
33+
"function": "timestamp_str_format",
34+
"mean_ms": total / ITERATIONS,
35+
"iterations": ITERATIONS,
36+
"total_ms": total,
37+
}))
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
"""Benchmark: value_counts with options — normalize=True, ascending=True, dropna=False."""
2+
import json
3+
import time
4+
import pandas as pd
5+
import numpy as np
6+
7+
ROWS = 100_000
8+
WARMUP = 3
9+
ITERATIONS = 20
10+
11+
data = [None if i % 500 == 0 else f"cat_{i % 50}" for i in range(ROWS)]
12+
s = pd.Series(data)
13+
14+
for _ in range(WARMUP):
15+
s.value_counts(normalize=True)
16+
s.value_counts(ascending=True)
17+
s.value_counts(dropna=False)
18+
s.value_counts(normalize=True, ascending=True, dropna=False)
19+
20+
start = time.perf_counter()
21+
for _ in range(ITERATIONS):
22+
s.value_counts(normalize=True)
23+
s.value_counts(ascending=True)
24+
s.value_counts(dropna=False)
25+
s.value_counts(normalize=True, ascending=True, dropna=False)
26+
total = (time.perf_counter() - start) * 1000
27+
28+
print(json.dumps({
29+
"function": "value_counts_opts",
30+
"mean_ms": total / ITERATIONS,
31+
"iterations": ITERATIONS,
32+
"total_ms": total,
33+
}))
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/**
2+
* Benchmark: DataFrame.sortValues with mixed ascending array [true, false, true].
3+
* Outputs JSON: {"function": "dataframe_sortvalues_mixed", "mean_ms": ..., "iterations": ..., "total_ms": ...}
4+
*/
5+
import { DataFrame } from "../../src/index.ts";
6+
7+
const ROWS = 100_000;
8+
const WARMUP = 3;
9+
const ITERATIONS = 20;
10+
11+
const df = DataFrame.fromColumns({
12+
category: Array.from({ length: ROWS }, (_, i) => `group_${i % 10}`),
13+
priority: Array.from({ length: ROWS }, (_, i) => i % 5),
14+
value: Array.from({ length: ROWS }, () => Math.random() * 1000),
15+
});
16+
17+
for (let i = 0; i < WARMUP; i++) {
18+
df.sortValues(["category", "priority", "value"], [true, false, true]);
19+
df.sortValues(["category", "value"], [false, true]);
20+
}
21+
22+
const start = performance.now();
23+
for (let i = 0; i < ITERATIONS; i++) {
24+
df.sortValues(["category", "priority", "value"], [true, false, true]);
25+
df.sortValues(["category", "value"], [false, true]);
26+
}
27+
const total = performance.now() - start;
28+
29+
console.log(
30+
JSON.stringify({
31+
function: "dataframe_sortvalues_mixed",
32+
mean_ms: total / ITERATIONS,
33+
iterations: ITERATIONS,
34+
total_ms: total,
35+
}),
36+
);
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/**
2+
* Benchmark: SeriesGroupBy.size() and SeriesGroupBy.getGroup() operations.
3+
* Outputs JSON: {"function": "series_groupby_size", "mean_ms": ..., "iterations": ..., "total_ms": ...}
4+
*/
5+
import { Series } from "../../src/index.ts";
6+
7+
const ROWS = 100_000;
8+
const WARMUP = 3;
9+
const ITERATIONS = 20;
10+
11+
const values = new Series({
12+
data: Array.from({ length: ROWS }, (_, i) => Math.random() * 1000),
13+
});
14+
const groups = new Series({
15+
data: Array.from({ length: ROWS }, (_, i) => `g${i % 20}`),
16+
});
17+
18+
for (let i = 0; i < WARMUP; i++) {
19+
values.groupby(groups).size();
20+
values.groupby(groups).getGroup("g0");
21+
values.groupby(groups).getGroup("g10");
22+
}
23+
24+
const start = performance.now();
25+
for (let i = 0; i < ITERATIONS; i++) {
26+
values.groupby(groups).size();
27+
values.groupby(groups).getGroup("g0");
28+
values.groupby(groups).getGroup("g10");
29+
}
30+
const total = performance.now() - start;
31+
32+
console.log(
33+
JSON.stringify({
34+
function: "series_groupby_size",
35+
mean_ms: total / ITERATIONS,
36+
iterations: ITERATIONS,
37+
total_ms: total,
38+
}),
39+
);

0 commit comments

Comments
 (0)